文本生成器
要记住一点,\(next[now][c]\)指向的是在\(now\)指向的这一节点所表示的字符串\(S\)再添加一个字母\(c\)所能形成的字符串。有两种可能,①存在\(S’=S+c\),②存在\(S'\)为\(S+c\)的最长真后缀,也就是说,要再目标串中看有多少模式串,只需要在遍历目标串的时候无脑往后面加字符\(c\)就好了,如果\(end[next[now][c]]\)不为0,则证明出现了\(next[now][c]\)所表示的字符串,而此时不管是情况①,还是情况②,都是表示某个模式串出现了。
// Created by CAD
#include <bits/stdc++.h>
using namespace std;
const int maxn=6005;
const int mod=1e4+7;
struct AC{
int next[maxn][30],fail[maxn],end[maxn];
int root,L;
int newnode(){
for(int i=0;i<26;++i)
next[L][i]=-1;
end[L++]=0;
return L-1;
}
void init(){
L=0;
root=newnode();
}
void insert(char buf[]){
int len=strlen(buf);
int now=root;
for(int i=0;i<len;++i){
int c=buf[i]-'A';
if(next[now][c]==-1)
next[now][c]=newnode();
now=next[now][c];
}
end[now]++;
}
void build(){
queue<int> Q;
fail[root]=root;
for(int i=0;i<26;++i){
if(next[root][i]==-1)
next[root][i]=root;
else {
fail[next[root][i]]=root;
Q.push(next[root][i]);
}
}
while(!Q.empty()){
int now=Q.front();Q.pop();
if(end[fail[now]]) end[now]=1;
for(int i=0;i<26;++i){
if(next[now][i]==-1)
next[now][i]=next[fail[now]][i];
else {
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
};
char buf[maxn];
int dp[105][maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;cin>>n>>m;
AC ac;
ac.init();
for(int i=1;i<=n;++i)
cin>>buf,ac.insert(buf);
ac.build();
dp[0][0]=1;
int ans=1;
for(int i=1;i<=m;++i){
for(int j=0;j<ac.L;++j){
for(int k=0;k<26;++k){
if(!ac.end[ac.next[j][k]]){
(dp[i][ac.next[j][k]]+=dp[i-1][j ])%=mod;
}
}
}
(ans*=26)%=mod;
}
for(int i=0;i<ac.L;++i)
(ans-=dp[m][i])%=mod;
cout<<(ans+mod)%mod<<endl;
return 0;
}
CAD加油!欢迎跟我一起讨论学习算法,QQ:1401650042