1. 程式人生 > 其它 >補題:Div2 #578 E. Compress Words

補題:Div2 #578 E. Compress Words

補題: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

*/