2020牛客多校第二场A.All with Pairs hash+kmp

https://ac.nowcoder.com/acm/contest/5667/A

题意:

给出n个字符串,f(s,t)代表字符串s的前缀和字符串t的后缀的最长匹配长度,求

思路:

官方题解:

 去重:只要我当前这个字符s[i]的Next[i]不为0,说明s[i]有更短的前缀也可以匹配,这里就会重复统计,但我们要求的是最长长度,就把短的减掉,Cnt[i]会统计当前这个前缀和所以后缀相等的个数,而Cnt[Next[i]]也会统计这里的个数,所以Cnt[Next[i]]-=Cnt[i]。

代码:

#include <bits/stdc++.h>
using namespace std;
const long long mod=998244353;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
const int MAXN=1e6+10;
string str[MAXN];
int Next[MAXN],cnt[MAXN];
map<ull,int>mp;
ull base=131;
void get_next(string str)
{
    int n=str.size();
    for(int i=2,j=0;i<n;i++)
    {
        while(j&&str[i]!=str[j+1])j=Next[j];
        if(str[i]==str[j+1])j++;
        Next[i]=j;
    }
}
void get_hash(string str)
{
    int n=str.size();
    ull p=1,sum=0;
    for(int i=n-1;i>=1;i--)
    {
        sum+=(str[i]-'a'+1)*p;
        p*=base;
        mp[sum]++;
    }
}
int main()
{

    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>str[i];
        str[i]=" "+str[i];
        get_hash(str[i]);
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        int len=str[i].size();
        ull sum=0;
        for(int j=1;j<len;j++)
        {
            sum=sum*base+(str[i][j]-'a'+1);
            cnt[j]=mp[sum];
        }
        get_next(str[i]);
        for(int j=1;j<len;j++)
        {
            if(Next[j]>0)cnt[Next[j]]-=cnt[j];
        }
        for(int j=1;j<len;j++)
        {
            ans=(ans+cnt[j]%mod*j%mod*j%mod)%mod;
        }
    }
    printf("%lld
",ans);

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/MZRONG/p/13413780.html