哈希-Codeforces Round #578 (Div. 2)-E.Compress Words

Codeforces Round #578 (Div. 2)-E.Compress Words
思路
给你一个英文句子n个字符串,n<=1e ^5,每个字符串长度<=1e ^6,要你把这n个单词依次拼成一个长单词并输出,在拼接时两个单词有相同且相邻的子串序列在长单词只保留1个,如句子:sample please ease in out,输出长单词:sampleaseinout。
哈希思想,把字符串表示为数字,方便比较。
题解

#include
#define ll long long
using namespace std;
const int maxn = 1e6 + 10;
ll h[3][maxn], base[3] = {43, 47, 41}, mod[3] = {1000000007, 998244353, 1000000009};
ll p[3][maxn];
int id(char c) {
    if (c >= 'a' && c <= 'z')
        return c - 'a';
    if (c >= '0' && c <= '9')
        return c - '0' + 26;
    return c - 'A' + 36;
}
char s[maxn], t[maxn];
ll gao(int l, int r, int i) {
    ll tmp = (h[i][r] - h[i][l - 1] * p[i][r - l + 1] % mod[i] + mod[i]) % mod[i];
    return tmp;
}
int main() {
    p[0][0] = p[1][0] = p[2][0] = 1;
    for (int i = 1; i < maxn; i++)
        for (int j = 0; j < 3; j++)
            p[j][i] = p[j][i - 1] * base[j] % mod[j];
    int q, n = 0;
    scanf("%d", &q);
    while (q--) {
        scanf("%s", t + 1);
        int len = strlen(t + 1);
        if (!n) {
            for (int i = 1; i <= len; i++) {
                s[++n] = t[i];
                for (int j = 0; j < 3; j++)
                    h[j][i] = (h[j][i - 1] * base[j] + id(t[i])) % mod[j];
            }
            continue;
        }
        int k = 1;
        ll tmp[3] = {0, 0, 0};
        for (int i = 1; i <= min(n, len); i++) {
            int ok = 1;
            for (int j = 0; j < 3; j++) {
                tmp[j] = (tmp[j] * base[j] + id(t[i])) % mod[j];
                if (gao(n - i + 1, n, j) != tmp[j])
                    ok = 0;
            }
            if (ok)
                k = i + 1;
        }
        //printf("k = %d\n", k);
        //puts(s + 1);
         for (int i = k; i <= len; i++) {
            s[++n] = t[i];
            for (int j = 0; j < 3; j++)
                h[j][n] = (h[j][n - 1] * base[j] + id(t[i])) % mod[j];
        }
    }
    s[++n] = '\0';
    puts(s + 1);
}

你可能感兴趣的:(哈希)