All with Pairs

A. All with Pairs

参考:A. All with Pairs (哈希值+next)

需要用到的东西是字符串哈希和前缀数组。

首先用字符串哈希将每一个后缀都统计一下,并用不同的后缀会映射为不同的哈希值,所以这样就可以在\(O(1)\)的时间复杂度内比较出两个字符串是否一样。

还要考虑到的事情是后缀为 abab 的字符串,也有在哈希表中有记录,所以当前缀为 abab 的字符串进行求值时,需要在 ab 中将 abab 的数目给减去,得到的才是真正的后缀为ab的个数。

// Created by CAD on 2020/7/16.
#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int maxs=1e6+5;
const int maxn=1e5+5;
const int mod=998244353;
ll bit[maxs],ans[maxs];
vector<ll> a[maxn];
unordered_map<ll,int> cnt;
ll base=217;
vector<int> Next[maxn];

void getNext(string t,int id)
{
    int i=0,j=-1,n=t.length();
    Next[id].resize(n+1);
    Next[id][0]=-1;
    while(i<n)
    {
        if(j==-1||t[i]==t[j])
            Next[id][++i]=++j;
        else j=Next[id][j];
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    bit[0]=1;
    for(int i=1;i<maxs;++i)
        bit[i]=bit[i-1]*base;
    int n;cin>>n;
    for(int i=1;i<=n;++i){
        string s;cin>>s;
        int slen=s.length();
        a[i].resize(slen+1);
        a[i][0]=0;
        for(int j=1; j <=slen; ++j)
            a[i][j]=a[i][j-1]*base+s[j-1];
        for(int j=1;j<=slen;++j){
            ll temp=a[i][slen]-a[i][slen-j]*bit[j];
            cnt[temp]++;
        }
        getNext(s,i);
    }
    ll Ans=0;
    for(int i=1;i<=n;++i){
        for(int j=1;j<Next[i].size();++j){
            ans[j]=cnt[a[i][j]];
            ans[Next[i][j]]-=ans[j];
        }
        for(int j=1;j<Next[i].size();++j)
            Ans=(Ans+ans[j]*j%mod*j%mod)%mod;
    }
    cout<<(Ans+mod)%mod<<endl;
    return 0;
}
posted @ 2020-07-16 12:59  caoanda  阅读(152)  评论(0编辑  收藏  举报