[BZOJ 1030][JSOI2007]文本生成器(AC自动机+DP)
2017-03-18 23:01
453 查看
Description
JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文
章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,
那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的
标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6
生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?
Input
输入文件的第一行包含两个正整数,分别是使用者了解的单词总数N (<= 60),GW文本生成器 v6生成的文本固定长度M;以下N行,每一行包含一个使用者了解的单词。这里所有单词及文本的长度不会超过100,并且只可能包
含英文大写字母A..Z
Output
一个整数,表示可能的文章总数。只需要知道结果模10007的值。Sample Input
2 2A
B
Sample Output
100Solution
答案可转化成 m26-不含所给字符串的方案数建一个AC自动机
Trie[Trie[p].next[i]].cnt|=Trie[Trie[Trie[p].next[i]].fail].cnt;(如果fail指针是单词结尾,该节点也不可取)
方案数可以用Dp来求
f[x][j]表示文章到第x位在第j个节点有多少方案
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #define Mod 10007 using namespace std; char word[101]; int n,m,siz,root,ans=0; int f[101][6006]; struct Node{ int fail,next[26],cnt; }Trie[6006]; int newnode() { Trie[++siz].fail=0; Trie[siz].cnt=0; memset(Trie[siz].next,0,sizeof(Trie[siz].next)); return siz; } void _insert(char *word) { int i=0,p=root; while(word[i]) { int idx=word[i]-'A'; if(!Trie[p].next[idx]) Trie[p].next[idx]=newnode(); p=Trie[p].next[idx]; i++; } Trie[p].cnt++; } void build() { queue<int>q; q.push(root); while(!q.empty()) { int p=q.front(); for(int i=0;i<26;i++) { int t=Trie[p].fail; while(t&&!Trie[t].next[i])t=Trie[t].fail; if(Trie[p].next[i]) { Trie[Trie[p].next[i]].fail=t?Trie[t].next[i]:root; Trie[Trie[p].next[i]].cnt|=Trie[Trie[Trie[p].next[i]].fail].cnt; q.push(Trie[p].next[i]); } else Trie[p].next[i]=t?Trie[t].next[i]:root; } q.pop(); } } void work(int x) { for(int i=1;i<=siz;i++) { for(int j=0;j<26;j++) { int t=Trie[i].next[j]; if(t&&!Trie[t].cnt) { f[x][t]+=f[x-1][i]; f[x][t]%=Mod; } } } } int Pow(int a,int n) { int res=1; while(n>0) { if(n&1)res*=a,res%=Mod; a=(a*a)%Mod; n>>=1; } return res; } int main() { siz=0,root=newnode(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%s",word); _insert(word); } build(); f[0][root]=1; for(int i=1;i<=m;i++)work(i); int ans=Pow(26,m); for(int i=1;i<=siz;i++)ans=(ans-f[m][i] 4000 +Mod)%Mod; printf("%d",ans); return 0; }
相关文章推荐
- bzoj1030: [JSOI2007]文本生成器(AC自动机+Dp)
- 【bzoj 1030】 [JSOI2007]文本生成器(AC自动机+dp)
- [BZOJ1030][JSOI2007]文本生成器(AC自动机+dp)
- bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)
- [BZOJ1030][JSOI2007]文本生成器(AC自动机+dp)
- bzoj 1030: [JSOI2007]文本生成器 (ac自动机上的dp)
- BZOJ1030 [JSOI2007]文本生成器 补全AC自动机+简单DP
- bzoj 1030: [JSOI2007]文本生成器(AC自动机+DP)
- BZOJ1030 [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
- [bzoj1030][JSOI2007]文本生成器——AC自动机
- [AC自动机 DP] BZOJ 1030 [JSOI2007] 文本生成器
- BZOJ 1030: [JSOI2007]文本生成器( AC自动机 + dp )
- BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]
- [Bzoj1030][JSOI2007]文本生成器(AC自动机)(dp)
- bzoj1030: [JSOI2007]文本生成器(AC自动机+DP)