1. 程式人生 > >luoguP4503 [CTSC2014]企鵝QQ hash

luoguP4503 [CTSC2014]企鵝QQ hash

既然只有一位的不同,那麼我們可以列舉這一位....

我們只需要快速地計算去掉某一位的$hash$值....

由於$hash(S) = \sum s[i] * seed^i$,因此去掉第$i$位的權值只需要用$hash(S) - s[i] * seed^i$

由於字串兩兩不相同,因此不存在兩個串去掉$i$和去掉$j$仍會保持相似

這樣子就可以做到不重的統計

複雜度$O(nL \log n)$

應該是可以用基排優化到$O(nL)$的...

#include <map>
#include <cstdio>
#include <cstring>
#include 
<algorithm> using namespace std; #define ll long long #define ri register int #define ull unsigned long long #define rep(io, st, ed) for(ri io = st; io <= ed; io ++) #define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define gc getchar inline int read() { int p = 0; char
c = gc(); while(c > '9' || c < '0') c = gc(); while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc(); return p; } const int seed = 19260817; const int sid = 30050; const int pid = 205; int n, L, S; char s[sid][pid]; ull wei[sid], val[sid], q[sid]; int main() { n
= read(); L = read(); S = read(); wei[0] = 1; rep(i, 1, L) wei[i] = wei[i - 1] * seed; rep(i, 1, n) { scanf("%s", s[i] + 1); rep(j, 1, L) val[i] += s[i][j] * wei[j]; } ll ans = 0; rep(i, 1, L) { rep(j, 1, n) q[j] = val[j] - s[j][i] * wei[i]; sort(q + 1, q + n + 1); for(ri i = 1, j = 1; i <= n; i = j + 1) { j = i; while(q[j + 1] == q[i]) j ++; ans += (j - i + 1) * (j - i) / 2; } } printf("%lld\n", ans); return 0; }