Codeforces 1200E(hash)

傳送門c++

題意:

給你n個串,要讓你把這個\(n\)個串拼接起來,其中,\(str_i\)的後綴以及\(str_{i+1}\)的前綴中最長的部分只能取一份。安全

分析:

本題中,咱們最主要須要解決的問題是如何快速的判斷一個串的後綴是否和另外一個串的前綴相同。而咱們知道,\(\text{hash}\)能夠在\(\mathcal{O}(1)\)的時間對兩個串進行比較。所以本題能夠用\(\text{hash}\)進行解決。spa

咱們只須要動態的去維護答案串的\(\text{hash}\)值,在更新匹配串的\(\text{hash}\)值的同時,將答案串的後綴不斷的跟匹配串的前綴匹配,並記錄匹配成功的位置\(pos\),最後咱們只須要根據獲得的\(pos\)更新答案串的\(\text{hash}\)便可。由於是\(\text{hash}\)值都是動態的進行更新,所以總體的時間複雜度爲:\(\mathcal{O}(\sum S)\)code

注意:由於整個串的長度已經到達了\(10^6\)的級別,所以爲了安全,建議使用雙\(\text{hash}\)ci

#include <bits/stdc++.h>
#define maxn 1000005
using namespace std;
const int mod1=1000000007;
const int mod2=19260817;
typedef long long ll;
typedef pair<ll,ll>pll;
pll hash1[maxn],hash2[maxn];
string str,ans;
ll p1[maxn],p2[maxn];
int main()
{
    p1[0]=p2[0]=1;
    for(int i=1;i<maxn;i++) p1[i]=p1[i-1]*131%mod1;
    for(int i=1;i<maxn;i++) p2[i]=p2[i-1]*133%mod2;

    int n;
    cin>>n;
    cin>>ans;
    for(int i=1;i<=ans.length();i++){
        hash1[i].first=(hash1[i-1].first*131+ans[i-1])%mod1;
        hash1[i].second=(hash1[i-1].second*133+ans[i-1])%mod2;
    }
    for(int i=2;i<=n;i++){
        cin>>str;
        int len1=ans.length(),len2=str.length();
        int pos=0;
        for(int j=1;j<=min(len1,len2);j++){
            hash2[j].first=(hash2[j-1].first*131+str[j-1])%mod1;
            hash2[j].second=(hash2[j-1].second*133+str[j-1])%mod2;
            pll t1;
            t1.first=((hash1[len1].first-hash1[len1-j].first*p1[j])%mod1+mod1)%mod1;
            t1.second=((hash1[len1].second-hash1[len1-j].second*p2[j])%mod2+mod2)%mod2;
            if(t1==hash2[j]) pos=j;
        }
        if(pos<len2) ans+=str.substr(pos);;
        for(int j=len1+1;j<=ans.length();j++){
            hash1[j].first=(hash1[j-1].first*131+ans[j-1])%mod1;
            hash1[j].second=(hash1[j-1].second*133+ans[j-1])%mod2;
        }
    }
    cout<<ans<<endl;
    return 0;
}
相關文章
相關標籤/搜索