题解 CF1200E 【Compress Words】

Soulist

2019-08-12 21:08:41

Solution

这道题也是非常毒了。。。 ~~主要是题意,我猜应该有很多人和我一样以为是合并$i$和$i-1$吧~~ ~~实际上~~题意是说每新读入一个新字符串就将其和已有的字符串合并。 $Sol.$ 考虑每次新加入一个单词,我们可以枚举一个长度,判断其前缀和已有字符串的后缀是否相同。 这个相同用$hash$判就好了。 然后暴力算的话复杂度会带个$\log$,所以还要预处理一下每个数前面的系数的$k$次方在$\%hash$意义下是多少。 这样就是$O(S)$了 ```cpp #include<bits/stdc++.h> using namespace std; #define rep( i, s, t ) for( register int i = s; i <= t; ++ i ) #define re register #define int long long int read() { char cc = getchar(); int cn = 0, flus = 1; while(cc < '0' || cc > '9') { if( cc == '-' ) flus = -flus; cc = getchar(); } while(cc >= '0' && cc <= '9') cn = cn * 10 + cc - '0', cc = getchar(); return cn * flus; } const int mod = 1e9 + 7 ; const int mod2 = 1e9 + 9 ; const int ha = 233 ; const int ha2 = 377 ; const int N = 1e6 + 5 ; int n, cnt, r, inv[N], inv2[N] ; char out[N], s[N] ; signed main() { n = read() ; int Maxa = 1e6 ; inv[0] = 1, inv2[0] = 1 ; rep( i, 1, Maxa ) inv[i] = ( inv[i - 1] * ha ) % mod, inv2[i] = ( inv2[i - 1] * ha2 ) % mod ; rep( i, 1, n ) { scanf("%s", s + 1 ) ; r = strlen( s + 1 ) ; int hash1 = 0, hash2 = 0 ; int hash12 = 0, hash22 = 0 ; int k = min( r, cnt ), ans = 0 ; rep( i, 1, k ) { hash1 = ( hash1 * ha + s[i] ) % mod ; hash2 = ( hash2 + out[cnt - i + 1] * inv[i - 1] ) % mod ; hash12 = ( hash12 * ha2 + s[i] ) % mod ; hash22 = ( hash22 + out[cnt - i + 1] * inv2[i - 1] ) % mod ; if( hash1 == hash2 && hash12 == hash22 ) ans = i ; } for( int i = ans + 1; i <= r; ++ i ) out[++ cnt] = s[i] ; } rep( i, 1, cnt ) printf("%c", out[i] ) ; return 0; } ```