[BZOJ1030][JSOI2007]文本生成器(AC自动机+dp)

来源:互联网 发布:韩国第一淘宝模特短发 编辑:程序博客网 时间:2024/04/29 13:55

题目:

我是超链接

题解:

f[i][j]表示第i位匹配到trie树中编号为j的节点,找可读的文章就是用总数减去不可读的文章

建fail树:如果一个节点的失配是结尾的话(不能选),那么这个节点也不能选

最后不要忘了+Mod)%Mod

代码:

#include <cstdio>#include <cstring>#include <queue>#define Mod 10007#define N 6005using 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);}

0 0