fi,j
表示前
i
个串,以
那么DP的转移可以用后缀自动机转移
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=4000010,P=1e9+7;
int n,cnt=1,len;
int nxt[N][30],fail[N],f[30],stp[N],t[N],r[N],g[N],p=1;
char a[N];
inline void extend(int x){
int np=++cnt; stp[np]=stp[p]+1;
while(p && !nxt[p][x]) nxt[p][x]=np,p=fail[p];
if(!p) fail[np]=1;
else{
int q=nxt[p][x];
if(stp[q]==stp[p]+1) fail[np]=q;
else{
int nq=++cnt; stp[nq]=stp[p]+1;
memcpy(nxt[nq],nxt[q],sizeof(nxt[nq]));
fail[nq]=fail[q];
fail[q]=fail[np]=nq;
while(p && nxt[p][x]==q) nxt[p][x]=nq,p=fail[p];
}
}
p=np;
}
int main(){
scanf("%d",&n);
while(n--){
scanf("%s",a+1); len=strlen(a+1);
for(int i=len;i;i--) extend(a[i]-'a');
for(int i=0;i<=cnt;i++) t[i]=0;
for(int i=1;i<=cnt;i++) t[stp[i]]++;
for(int i=1;i<=cnt;i++) t[i]+=t[i-1];
for(int i=1;i<=cnt;i++) r[t[stp[i]]--]=i;
for(int i=cnt;i;i--){
int x=r[i]; g[x]=1;
for(int j=0;j<26;j++)
if(nxt[x][j]) (g[x]+=g[nxt[x][j]])%=P;
else (g[x]+=f[j])%=P;
}
for(int i=0;i<26;i++)
if(nxt[1][i]) f[i]=g[nxt[1][i]];
for(int i=1;i<=cnt;i++){
stp[i]=fail[i]=0;
for(int j=0;j<26;j++) nxt[i][j]=0;
}
cnt=p=1;
}
int ans=0;
for(int i=0;i<26;i++) (ans+=f[i])%=P;
printf("%d\n",ans+1);
}