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;
}
CAD加油!欢迎跟我一起讨论学习算法,QQ:1401650042