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<bits\stdc++.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\n",x)
#define putl(x) printf("%lld\n",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;
}
posted @ 2020-07-14 16:10  chdy  阅读(120)  评论(0编辑  收藏  举报