传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3277
广义后缀自动机上dp
建出广义后缀自动机之后直接跳parent树去更新就没了w
具体实现看代码吧
#include <bits/stdc++.h> using namespace std; string s[1000005]; int fa[1000005],tot=1,N,K,Len[1000005],Son[1000005][26],rt=1,las=1,vis[1000005],cnt[1000005],Sum[1000005]; void Insert(int x){ int now=++tot,pre=las; las=now; Len[now]=Len[pre]+1; for (;pre&&!Son[pre][x];pre=fa[pre]) Son[pre][x]=now; if (!pre) fa[now]=rt; else{ int q=Son[pre][x]; if (Len[q]==Len[pre]+1) fa[now]=q; else{ int nq=++tot; Len[nq]=Len[pre]+1; memcpy(Son[nq],Son[q],sizeof(Son[q])); fa[nq]=fa[q]; fa[q]=fa[now]=nq; for(;pre&&Son[pre][x]==q; pre=fa[pre]) Son[pre][x]=nq; } } } void Times(){ for (int i=1;i<=N;i++){ int now=rt; for (int j=0;j<s[i].length();j++){ now=Son[now][s[i][j]-'a']; int qwq=now; for (;qwq&&vis[qwq]!=i;) vis[qwq]=i,cnt[qwq]++,qwq=fa[qwq]; } } } void dfs(int x){ if (x==rt||vis[x]) return; vis[x]=1; dfs(fa[x]); Sum[x]+=Sum[fa[x]]; } int main(){ cin>>N>>K; for (int i=1;i<=N;i++) cin>>s[i]; for (int i=1;i<=N;i++){ las=1; for (int j=0;j<s[i].length();j++){ Insert(s[i][j]-'a'); } } Times(); for (int i=1;i<=tot;i++) Sum[i]=(cnt[i]>=K)*(Len[i]-Len[fa[i]]); memset(vis,0,sizeof(vis)); for (int i=1;i<=tot;i++) dfs(i); for (int i=1;i<=N;i++){ int ans=0,now=rt; for (int j=0;j<s[i].length();j++) now=Son[now][s[i][j]-'a'],ans+=Sum[now]; printf("%d ",ans); } return 0; }