题目:
题解:
f[i][j]表示第i位匹配到trie树中编号为j的节点,找可读的文章就是用总数减去不可读的文章
建fail树:如果一个节点的失配是结尾的话(不能选),那么这个节点也不能选
最后不要忘了+Mod)%Mod
代码:
#include <cstdio>
#include <cstring>
#include <queue>
#define Mod 10007
#define N 6005
using namespace std;
int ch[N][30],tot,fail[N],f[105][N];
bool is_end[N];
void trie()
{
char st[120];
scanf("%s",st);
int l=strlen(st),now=0;
for (int i=0;i<l;i++)
{
int x=st[i]-'A';
if (!ch[now][x]) ch[now][x]=++tot;
now=ch[now][x];
}
is_end[now]=true;
}
void sp()
{
queue <int> q;
int i;
for (i=0;i<26;i++)
if (ch[0][i]) q.push(ch[0][i]);
while (!q.empty())
{
int now=q.front(); q.pop();
for (i=0;i<26;i++)
{
if (!ch[now][i])
{
ch[now][i]=ch[fail[now]][i];
continue;
}
if (is_end[ch[fail[now]][i]]) is_end[ch[now][i]]=true;
fail[ch[now][i]]=ch[fail[now]][i];
q.push(ch[now][i]);
}
}
}
int main()
{
int n,m,i,j,k;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
trie();
sp();
f[0][0]=1;
for (i=1;i<=m;i++)
for (j=0;j<=tot;j++)
{
if (is_end[j] || !f[i-1][j]) continue;
for (k=0;k<26;k++)
f[i][ch[j][k]]=(f[i][ch[j][k]] + f[i-1][j]%Mod)%Mod;
}
int cnt1=1,cnt2=0;
for (i=1;i<=m;i++)
cnt1=(cnt1*26)%Mod;
for (i=0;i<=tot;i++)
if (!is_end[i])
cnt2=(cnt2+f[m][i])%Mod;
printf("%d",(cnt1-cnt2+Mod)%Mod);
}