您的位置:首页 > Web前端 > JavaScript

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

2017-03-17 10:27 344 查看
题目:

我是超链接

题解:

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
[30],tot,fail
,f[105]
;
bool is_end
;
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: