BZOJ_1030_[JSOI2007]_文本生成器_(AC自动机+DP)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1030
给出一些单词,问长度为\(m\)的文章有多少文章中出现过任意一个或多个单词.
分析
文章总数为\(26^m\),减去没有出现过任意单词的文章数量就是答案.
那么如何求"没有出现过任意单词的文章的数量"呢?
我们用所有单词建立一个AC自动机,那么问题就转化成了在AC自动机上跑\(m\)步(相当于边跑边枚举),不经过单词节点(相当于没有单词成功匹配).在AC自动机上dp即可.
\(dp[i][j]\)表示文章的第\(i\)个字母在自动机的\(j\)号节点上的方案数.那么最终答案就是\(\sum_{i=0}^{sz}dp[m][i]\).
注意\(i\)是从0开始的,因为当走到AC自动机上没有的节点时就会走到0节点.
#include <bits/stdc++.h> using namespace std; const int maxn=6000+5,maxm=100+5,type=26,mod=10007; int n,m,a=1,b; int dp[maxm][maxn]; char s[maxm]; struct Aho_Corasick{ int sz,ch[maxn][type],f[maxn],q[maxn]; bool val[maxn]; Aho_Corasick(){ memset(val,false,sizeof val); } inline void ins(char *s){ int u=0,m=strlen(s+1); for(int i=1;i<=m;i++){ int c=s[i]-'A'; if(!ch[u][c]) u=ch[u][c]=++sz; else u=ch[u][c]; } val[u]=true; } inline void get_fail(){ int L=1,R=0; for(int c=0;c<type;c++){ int u=ch[0][c]; if(u){ f[u]=0;q[++R]=u; } } while(L<=R){ int u=q[L++]; for(int c=0;c<type;c++){ if(!ch[u][c]){ ch[u][c]=ch[f[u]][c]; continue; } f[ch[u][c]]=ch[f[u]][c]; if(val[ch[f[u]][c]]) val[ch[u][c]]=true; q[++R]=ch[u][c]; } } } inline void DP(int x){ for(int i=0;i<=sz;i++){ if(val[i]||!dp[x-1][i]) continue; for(int j=0;j<type;j++){ if(!val[ch[i][j]]) dp[x][ch[i][j]]=(dp[x][ch[i][j]]+dp[x-1][i])%mod; } } } }ac; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%s",s+1); ac.ins(s); } ac.get_fail(); dp[0][0]=1; for(int i=1;i<=m;i++) ac.DP(i); for(int i=1;i<=m;i++) a=(a*type)%mod; for(int i=0;i<=ac.sz;i++) b=(b+dp[m][i])%mod; printf("%d\n",(a-b+mod)%mod); return 0; }View Code
1030: [JSOI2007]文本生成器
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3588 Solved: 1463
[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 2A
B
Sample Output
100HINT
Source
- js实现图片切换轮播终极版
- js字典算法
- JSON和JSONP
- js 函数报错“Uncaught: TypeError xxx is not a function”
- Start My JS Road
- Augularjs-起步
- js兼容性大全(持续更新)
- 倒计时js代码 时分秒-天时分秒
- JavaScript url 编码转换
- rotate点击来回旋转和同一事件绑定解决同一class写法
- js点击a标签切换不同列表
- Native.js示例汇总
- Javascript 严格模式use strict详解
- javascript案例——倒计时效果
- [Sencha ExtJS6 Modern] 改进bug: 当store.remove/removeAt执行之后,DataView的对应item的dom没有移除
- jsoup解析html
- PHP之JavaScript
- JS中的prototype
- jsp遍历、循环
- javascript 变量声明 和 作用域