[BZOJ]1030: [JSOI2007]文本生成器 AC自动机+DP
2017-09-14 22:16
337 查看
Description
JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,
他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文
章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,
那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的
标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6
生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?
JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,
他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文
章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,
那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的
标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6
生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?
题解:
复习AC自动机。考虑用总数减去不合法的方案,一种不合法方案为在AC自动机上走m步,没有走到过一个标记过的点(也就是一个单词的结尾)。我们设设f[i][j]表示走i步,现在在j号节点的路径条数,就可以了。代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int mod=10007; const int maxn=105; struct Trie{int son[27],fail;}tr[21000]; bool end[211000]; int n,m,z=0,f[maxn][21000]; char str[maxn]; void Clear(int x) { tr[x].fail=0; for(int i=0;i<26;i++)tr[x].son[i]=-1; } void Build_Trie() { int len=strlen(str),now=0; for(int i=0;i<len;i++) { int x=str[i]-'A'; if(tr[now].son[x]==-1)tr[now].son[x]=++z,Clear(z); now=tr[now].son[x]; } end[now]=true; } queue<int>q; void work() { q.push(0); while(!q.empty()) { int x=q.front();q.pop(); end[x]|=end[tr[x].fail]; for(int i=0;i<26;i++) { int Son=tr[x].son[i],Fail=tr[x].fail; if(Son>=0) { if(!x)tr[Son].fail=0; else tr[Son].fail=tr[Fail].son[i]; q.push(Son); } else if(!x)tr[x].son[i]=0; else tr[x].son[i]=tr[Fail].son[i]; } } } void print(int x) { printf("%d: ",x); for(int i=0;i<26;i++) printf("%d ",tr[x].son[i]); puts(""); } int main() { memset(f,0,sizeof(f)); memset(end,false,sizeof(end));Clear(0); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%s",str); Build_Trie(); } //设f[i][j]表示走i步,现在在j号节点的路径条数。 work(); f[0][0]=1; for(int i=1;i<=m;i++) for(int j=0;j<=z;j++) if(!end[j]&&f[i-1][j]) { for(int k=0;k<26;k++) f[i][tr[j].son[k]]+=f[i-1][j],f[i][tr[j].son[k]]%=mod; } int ans1=1,ans2=0; for(int i=1;i<=m;i++)ans1=ans1*26%mod; // for(int i=0;i<=z;i++)print(i); for(int i=0;i<=z;i++) if(!end[i])ans2=(ans2+f[m][i])%mod; printf("%d",(ans1-ans2+mod)%mod); }
相关文章推荐
- [BZOJ1030]-[JSOI2007]文本生成器-AC自动机+dp
- BZOJ1030 [JSOI2007]文本生成器(AC自动机+dp)
- [BZOJ1030][JSOI2007]文本生成器(AC自动机+dp)
- [bzoj1030][JSOI2007]文本生成器——AC自动机
- [BZOJ1030][JSOI2007]文本生成器(AC自动机+dp)
- BZOJ_1030_[JSOI2007]_文本生成器_(AC自动机+DP)
- 【bzoj 1030】 [JSOI2007]文本生成器(AC自动机+dp)
- bzoj 1030: [JSOI2007]文本生成器 (ac自动机上的dp)
- bzoj1030: [JSOI2007]文本生成器(AC自动机+Dp)
- [BZOJ 1030][JSOI2007]文本生成器(AC自动机+DP)
- bzoj 1030: [JSOI2007]文本生成器(AC自动机+DP)
- BZOJ1030 [JSOI2007]文本生成器 补全AC自动机+简单DP
- bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)
- bzoj1030 [JSOI2007]文本生成器(AC+dp)
- AC自动机1030 [JSOI2007]文本生成器
- bzoj 1030: [JSOI2007]文本生成器 (ac自己主动机上的dp)
- 【bzoj1030】[JSOI2007]文本生成器
- BZOJ 1030 【JSOI2007】 文本生成器
- 【bzoj 1030】文本生成器(AC自动机+DP)
- BZOJ 1030: [JSOI2007]文本生成器 AC自动机