既然只有一位的不同,那么我们可以枚举这一位....
我们只需要快速地计算去掉某一位的$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 ", ans); return 0; }