• Codeforces 1200E(hash)


    传送门

    题意:

    给你n个串,要让你把这个(n)个串拼接起来,其中,(str_i)的后缀以及(str_{i+1})的前缀中最长的部分只能取一份。

    分析:

    本题中,我们最主要需要解决的问题是如何快速的判断一个串的后缀是否和另一个串的前缀相同。而我们知道,( ext{hash})可以在(mathcal{O}(1))的时间对两个串进行比较。因此本题可以用( ext{hash})进行解决。

    我们只需要动态的去维护答案串的( ext{hash})值,在更新匹配串的( ext{hash})值的同时,将答案串的后缀不断的跟匹配串的前缀匹配,并记录匹配成功的位置(pos),最后我们只需要根据得到的(pos)更新答案串的( ext{hash})即可。因为是( ext{hash})值都是动态的进行更新,因此整体的时间复杂度为:(mathcal{O}(sum S))

    注意:因为整个串的长度已经到达了(10^6)的级别,因此为了安全,建议使用双( ext{hash})

    #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;
    }
    
  • 相关阅读:
    行列式学习笔记
    二项式反演学习笔记
    【AtCoder】ARC096(C
    【LOJ】#2127. 「HAOI2015」按位或
    [ACM] POJ 1218 THE DRUNK JAILER (关灯问题)
    lua的弱弱引用表
    西班牙式软件团队
    【DRP】採用dom4j完毕XML文件导入数据库
    基于Linux平台病毒Wirenet.c解析
    【剑指offer】异或去重
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11346491.html
Copyright © 2020-2023  润新知