欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 前端技术 > javascript >内容正文

javascript

BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]

发布时间:2025/3/20 javascript 44 豆豆
生活随笔 收集整理的这篇文章主要介绍了 BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP] 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

1030: [JSOI2007]文本生成器

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3953  Solved: 1614
[Submit][Status][Discuss]

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 2
A
B

Sample Output

100
题意:求长度为m且含有至少一个模板串的字符串个数
好神啊 含有至少一个不好求,那就求不含模板串的然后总数减 计数问题组合数学做不了就考虑DP f[i][j]表示长度为i匹配到自动机上节点j的不含模板串的方案数 转移 f[i][j]-->f[i+1][t[j].ch[k]] 如何判断一个串不含模板串?首先f[i][j]已经保证1..i-1是不含模板串的啦,只要保证第i个字符加入后也不含就行了 ins时模板串终点打标记,本身且Fail祖先没有标记就说明AC自动机上j结尾的没有模板串 但是有的字符模板串里没有啊?给root把孩子补全就行了【实际上不补全也是可以的,反正默认走到了根,最后f[m][根]也统计】 思路和KMP一样,都是一边生成字符串一边在KMP/AC自动机上匹配, #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=105,M=6005,MOD=10007; int n,m; char s[N]; struct node{int ch[26],fail,val; }t[M]; int sz; void ins(char s[]){int u=0,n=strlen(s+1);for(int i=1;i<=n;i++){int c=s[i]-'A';if(!t[u].ch[c]) t[u].ch[c]=++sz;u=t[u].ch[c];}t[u].val=1; } int q[M],head,tail; void getAC(){head=tail=1;for(int i=0;i<26;i++){if(!t[0].ch[i]) t[0].ch[i]=++sz;q[tail++]=t[0].ch[i];}while(head!=tail){int u=q[head++];t[u].val|=t[t[u].fail].val;for(int i=0;i<26;i++){int &v=t[u].ch[i];if(!v) {v=t[t[u].fail].ch[i];continue;}t[v].fail=t[t[u].fail].ch[i];q[tail++]=v;}} } int f[N][M],ans; void dp(){f[0][0]=1;for(int i=1;i<=m;i++){for(int j=0;j<=sz;j++) if(!t[j].val&&f[i-1][j]!=0)for(int k=0;k<26;k++) if(!t[t[j].ch[k]].val)f[i][t[j].ch[k]]=(f[i][t[j].ch[k]]+f[i-1][j])%MOD;}for(int j=0;j<=sz;j++) ans=(ans+f[m][j])%MOD; } int main(){//freopen("in.txt","r",stdin);scanf("%d%d",&n,&m);//printf("hi %d %d nm\n",n,m);for(int i=1;i<=n;i++) scanf("%s",s+1),ins(s);getAC();dp();int tmp=1;for(int i=1;i<=m;i++) tmp=(tmp*26)%MOD;printf("%d",(tmp-ans+MOD)%MOD); }

 

总结

以上是生活随笔为你收集整理的BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。