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\n",ans); return 0; }