1. 程式人生 > 實用技巧 >2020牛客多校第二場A.All with Pairs hash+kmp

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