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;
}

猜你喜欢

转载自www.cnblogs.com/reverymoon/p/9951910.html