zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营 第二场 A All with Pairs 字符串hash KMP

    LINK:All with Pairs

    那天下午打这个东西的时候状态极差 推这个东西都推了1个多小时 (比赛是中午考试的我很困 没睡觉直接开肝果然不爽

    一开始看错匹配的位置了 以为是(1-l)(r-(r-l+1))进行匹配。

    我想这不是随便写个trie树???码完发现过不去样例 我真的是眼瞎

    后来看清了。

    大致思路如下 可以直接暴力枚举(n^2)个点对 找到最大的匹配位置这个也可以暴力 由于串长总和是M。

    这一部分复杂度也不过是(n^2+M)的。

    过不了 就可以思考能不能从大到小枚举匹配长度 看有多少对符合。

    发现这样也非常难做。

    不过可以对单个串枚举匹配长度 然后看有多少个串可以进行匹配。

    这样容易想到字符串hash 来进行快速的匹配 开C++11 直接unodered_map...

    然后可以发现这样做 会带来重复 仔细观察对于同一个串的重复位置 可以发现这是一个KMP的nex数组的问题。

    然后每次统计到一个位置就把自己的nex数组的那个位置给减掉即可。

    code
    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000000000ll
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 13331
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define uint unsigned long long
    #define ui unsigned
    #define EPS 1e-4
    #define sq sqrt
    #define S second
    #define F first
    #define len(x) t[x].len
    #define en(x) t[x].en
    #define mod 998244353
    #define M 1000000007
    using namespace std;
    const int MAXN=100010,maxn=1000010;
    int n,cnt;
    string a[MAXN];ll c[maxn];
    map<ll,int>H[maxn];
    ll p[maxn];
    char b[maxn];
    int nex[maxn];ll w[maxn];
    inline void kmp(int n)
    {
        int j=0;
        rep(2,n,i)
        {
            while(j&&b[j+1]!=b[i])j=nex[j];
            if(b[j+1]==b[i])++j;
            nex[i]=j;
        }
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        ios::sync_with_stdio(false);
        cin>>n;int mx=0;
        rep(1,n,i)
        {
            cin>>a[i];
            mx=max(mx,(int)a[i].size());
            ll ha=0;
            vep(0,a[i].size(),j)
            {
                ha=(ha*P%M+(a[i][j]-'a'+1))%M;
                ++H[j+1][ha];
            }
        }
    	p[0]=1;
        rep(1,mx,i)p[i]=(ll)p[i-1]*P%M;
        rep(1,n,i)
        {
            ll ha=0;
            reverse(a[i].begin(),a[i].end());
            int cnt=0;
            vep(0,a[i].size(),j)b[++cnt]=a[i][j],w[cnt]=0;
            kmp(cnt);cnt=0;
            vep(0,a[i].size(),j)
            {
                ++cnt;
                ha=(ha+(a[i][j]-'a'+1)*(ll)p[cnt-1])%M;
                if(H[cnt].find(ha)!=H[cnt].end())
                {
                    ll cc=H[cnt][ha];
                    c[cnt]+=cc;
                    w[nex[cnt]]+=cc;
                }
            }
            rep(1,cnt,j)c[j]-=w[j];
        }
        ll ans=0;
        fep(mx,1,i)ans=(ans+(ll)i*i*c[i])%mod;
        cout<<ans<<endl;return 0;
    }
    
  • 相关阅读:
    从零开始写STL-容器-双端队列
    JVM 总结
    从零开始写STL-容器-list
    从零开始写STL—容器—vector
    Web 后端编程的几个关键点(总结中...)
    Java Web 总结
    Spring实战读书笔记
    MSDN 同步部分 个人笔记
    洛谷 P3391【模板】文艺平衡树(Splay)
    洛谷 P1503 鬼子进村
  • 原文地址:https://www.cnblogs.com/chdy/p/13299656.html
Copyright © 2011-2022 走看看