補題:Div2 #578 E. Compress Words
阿新 • • 發佈:2021-07-15
補題:Div2 #578 E. Compress Words
從第一個單詞開始,如果前一個單詞的字尾和後一個單詞的字首相同,那麼把他們合併,求最後合併後的串
每新讀入一個新字串就將其和已有的字串合併,不是合併i和i-1
想法就是對想合併的兩個串求雜湊值,然後列舉能合併的字首字尾的長度
單模數hash在codeforces上很容易被hack的,建議雙模數hash
如果時間超限的話,可以考慮預處理快速冪,能少個log
(hash查詢是O(1)的,所以在某些情況下可以往稍稍暴力的方面想)
(太久沒寫被卡細節=_=)
#include<bits/stdc++.h> using namespace std; #define PI acos(-1) #define ll long long #define clean(a,b) memset(a,b,sizeof(a)) const int inf=0x3f3f3f3f; const int maxn=1e6+9; const int mod=1e9+7; const int mod_=1e9+9; inline ll read() { register ll x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } string s[maxn]; int base=131; ll _hash[1000009][6]; int fpo[maxn][3]; ll fpow(ll a,ll b,ll c) { a%=c; ll ans=1; while(b) { if(b&1) ans=ans*a%c; a=a*a%c; b>>=1; } return ans%c; } int get_hash(int l,int r,int x) { return (_hash[r+1][x]-_hash[l][x]*fpo[r-l+1][1]%mod+mod)%mod; } int get_hash_(int l,int r,int x) { return (_hash[r+1][x]-_hash[l][x]*fpo[r-l+1][2]%mod_+mod_)%mod_; } int main() { #ifdef LOCAL freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif for(int i=1;i<=1e6;i++) fpo[i][1]=fpow(base,i,mod)%mod,fpo[i][2]=fpow(base,i,mod_)%mod_; int n=read(); cin>>s[1]; int len=s[1].size(); // int now=2;//now for(int i=0;i<len;i++) { _hash[i+1][1]=((_hash[i][1]*base)+s[1][i])%mod; _hash[i+1][3]=((_hash[i][3]*base)+s[1][i])%mod_; } string ans=s[1]; for(int i=2;i<=n;i++) { cin>>s[i]; int len=s[i].size(); int anslen=ans.size(); int nowlen=min(len,anslen); for(int j=0;j<len;j++) { _hash[j+1][2]=((_hash[j][2]*base)+s[i][j])%mod; _hash[j+1][4]=((_hash[j][4]*base)+s[i][j])%mod_; } int anss=0; for(int j=1;j<=nowlen;j++) { ll hash_1=get_hash(anslen-j,anslen-1,1); ll hash_2=get_hash(0,j-1,2); ll hash_3=get_hash_(anslen-j,anslen-1,3); ll hash_4=get_hash_(0,j-1,4); if(hash_1==hash_2) anss=j; } for(int j=anss;j<len;j++) { int k=j-anss+anslen; _hash[k+1][1]=((_hash[k][1]*base)+s[i][j])%mod; _hash[k+1][3]=((_hash[k][3]*base)+s[i][j])%mod_; ans+=s[i][j]; } } cout<<ans; return 0; } /* 12345678 678945646 */