AC自动机 【JSOI2007】bzoj1030 文本生成器
2016-12-27 19:43
411 查看
题目大意:
给出N个由大写字母组成的字符串,再给出一个长度M
求有多少个由大写字母组成的长度为M的字符串满足“至少包含这N个字符串中的一个”
答案对10007取模
题目分析:
直接求满足至少包含N个字符串中一个的字符串个数不好求,那我们可以求一个都不包含的个数,再用总个数(26^M)减去就可以了。
把所有的串扔到AC自动机中,我们避开单词节点做DP;
设f[i][j]代表到第i个字符,是第j个状态的不包含任何给出的字符串的方案数
f[i+1][k]+=f[i][j] (k是j的一个儿子且j与k都不是单词节点);
注意事项:
1、要注意一个字符串包含另一个字符串的情况;
2、DP用循环写,不要用递归(我原来用dfs写的,TLE,很糟糕,当然聪明的读者会有比我更好的方法)
3、f[0][0]赋值为1;
4、最后在模意义下做减法最好加上mod再取余mod。
代码如下:
给出N个由大写字母组成的字符串,再给出一个长度M
求有多少个由大写字母组成的长度为M的字符串满足“至少包含这N个字符串中的一个”
答案对10007取模
题目分析:
直接求满足至少包含N个字符串中一个的字符串个数不好求,那我们可以求一个都不包含的个数,再用总个数(26^M)减去就可以了。
把所有的串扔到AC自动机中,我们避开单词节点做DP;
设f[i][j]代表到第i个字符,是第j个状态的不包含任何给出的字符串的方案数
f[i+1][k]+=f[i][j] (k是j的一个儿子且j与k都不是单词节点);
注意事项:
1、要注意一个字符串包含另一个字符串的情况;
2、DP用循环写,不要用递归(我原来用dfs写的,TLE,很糟糕,当然聪明的读者会有比我更好的方法)
3、f[0][0]赋值为1;
4、最后在模意义下做减法最好加上mod再取余mod。
代码如下:
#include<cstdio> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmath> #include<cstring> #define N 6060 using namespace std; const int mod=10007; int n,m,l,r; char s[200]; int f[110] ; struct trie{ trie *son[26],*fail; bool dc;int pos; trie() { memset(son,0,sizeof(son)); fail=NULL;dc=false; } void inser(char *s) { trie *c=this; for(int i=0;s[i];i++) { if(!c->son[s[i]-'A']) c->son[s[i]-'A']=new trie(); c=c->son[s[i]-'A']; } c->dc=true; } }*V=new trie,*dl ; void Aho_Corasick_Automaton(trie *V) { l=1;r=0; V->fail=V;V->pos=0; for(int i=0;i<26;i++) { if(!V->son[i]) V->son[i]=V; else {dl[++r]=V->son[i];V->son[i]->fail=V;} } trie *c,*t; while(l<=r) { c=dl[l++]; c->pos=l-1; for(int i=0;i<26;i++) { if(!c->son[i]) c->son[i]=c->fail->son[i]; else { dl[++r]=c->son[i]; c->son[i]->fail=c->fail->son[i]; c->son[i]->dc|=c->fail->son[i]->dc; } } } return; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%s",s); V->inser(s); } Aho_Corasick_Automaton(V); f[0][0]=1; dl[0]=V; for(int i=0;i<m;i++) for(int j=0;j<=r;j++) if(!dl[j]->dc) for(int k=0;k<26;k++) f[i+1][dl[j]->son[k]->pos]=(f[i+1][dl[j]->son[k]->pos]+f[i][j])%mod; int ans=1,a=26,t=m; while(t) { if(t&1) ans=(ans*a)%mod; a=(a*a)%mod; t>>=1; } for(int i=0;i<=r;i++) { if(dl[i]->dc) continue; ans=(ans-f[m][dl[i]->pos]+mod)%mod; } printf("%d\n",ans); return 0; }
相关文章推荐
- BZOJ 1030: [JSOI2007]文本生成器( AC自动机 + dp )
- 【BZOJ1030】【JSOI2007】文本生成器(AC自动机,DP)
- BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]
- [AC自动机 + DP] BZOJ1030: [JSOI2007]文本生成器
- [JSOI2007][BZOJ1030] 文本生成器|AC自动机|动态规划
- [BZOJ1030] [JSOI2007]文本生成器(AC自动机 + DP)
- [AC自动机 DP] BZOJ 1030 [JSOI2007] 文本生成器
- BZOJ1030 [JSOI2007]文本生成器(AC自动机)
- 【BZOJ1030】[JSOI2007]文本生成器【AC自动机】【计数DP】
- 【AC自动机】【bzoj 1030】: [JSOI2007]文本生成器
- BZOJ 1030: [JSOI2007]文本生成器 AC自动机
- [bzoj1030][JSOI2007]文本生成器【AC自动机】
- BZOJ 1030 [JSOI2007]文本生成器(AC自动机)
- BZOJ 1030: [JSOI2007]文本生成器 AC自动机
- BZOJ 1030 [JSOI2007]文本生成器 (AC自动机 + DP)
- 【BZOJ 1030】【JSOI 2007】文本生成器 AC自动机+递推
- [BZOJ]1030 [JSOI2007] 文本生成器 AC自动机 + DP
- BZOJ 1030: [JSOI2007]文本生成器 DP,AC自动机
- [Bzoj1030][JSOI2007]文本生成器(AC自动机)(dp)
- bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)