bzoj 1030: [JSOI2007]文本生成器 (ac自动机上的dp)
来源:互联网 发布:有什么软件推广 编辑:程序博客网 时间:2024/04/28 22:04
1030: [JSOI2007]文本生成器
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2635 Solved: 1090
[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
A
B
Sample Output
100
ac自动机上的dp
dp[0][i][j]表示到第i位,以第j个状态结束不符合条件的串的个数
dp[1][i][j]表示到第i位,以第j个状态结束符合条件的串的个数
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 6005;const int MOD = 10007;int que[N], fr, ta;struct ACM {int cnt;int nxt[N][26], sum[N], fail[N];void init() {for(int i = 1; i <= cnt; ++i) {sum[i] = fail[i] = 0;for(int j = 0; j < 26; ++j)nxt[i][j] = 0;}cnt = 1;for(int i = 0; i < 26; ++i) nxt[0][i] = 1;}void insert(string str) {int now = 1;int len = str.length();for(int i = 0; i < len; ++i) {if(nxt[now][str[i] - 'A'] == 0) nxt[now][str[i] - 'A'] = ++cnt;now = nxt[now][str[i] - 'A'];}sum[now] = 1;}void build_fail() {fr = ta = 0;que[ta++] = 1;fail[1] = 0;while(fr != ta) {int now = que[fr++];for(int i = 0; i < 26; ++i) {int x = nxt[now][i];if(x == 0) continue;int tmp = fail[now];while(nxt[tmp][i] == 0) tmp = fail[tmp];fail[x] = nxt[tmp][i];que[ta++] = x;}}}void debug() {for(int i = 1; i <= cnt; ++i) {cout<<i<<": "<<"fail = "<<fail[i]<<" [ ";for(int j = 0; j < 26; ++j) {if(nxt[i][j]) cout<<char(j + 'A')<<','<<nxt[i][j]<<' ';}puts("]");}}void gao(int, int);} acm;int dp[2][105][N];void ACM::gao(int n, int m) {build_fail();//debug();memset(dp, 0, sizeof(dp));dp[0][0][1] = 1;for(int i = 1; i <= m; ++i) {for(int j = 1; j <= cnt; ++j) {int u = j;for(int k = 0; k < 26; ++k) {int v = u;while(nxt[v][k] == 0) v = fail[v];v = nxt[v][k];if(sum[v]) {dp[1][i][v] = (dp[1][i][v] + dp[1][i - 1][u] + dp[0][i - 1][u]) % MOD;dp[0][i][v] += 0;} else {dp[1][i][v] = (dp[1][i][v] + dp[1][i - 1][u]) % MOD;dp[0][i][v] = (dp[0][i][v] + dp[0][i - 1][u]) % MOD;}}}}int ans = 0;for(int i = 1; i <= cnt; ++i)ans = (ans + dp[1][m][i]) % MOD;cout<<ans<<endl;}string str[65];bool ok(int x, int n) {int len = str[x].length();for(int i = 0; i < n; ++i) {if(i == x) continue;int pos = str[x].find(str[i]);if(pos >= 0 && pos < len) return false;}return true;}int main() {int n, m;cin>>n>>m;acm.init();for(int i = 0; i < n; ++i) {cin>>str[i];}sort(str, str + n);n = unique(str, str + n) - str;for(int i = 0; i < n; ++i) {if(ok(i, n)) acm.insert(str[i]);}acm.gao(n, m);return 0;}
0 0
- bzoj 1030: [JSOI2007]文本生成器 (ac自动机上的dp)
- BZOJ 1030 JSOI2007 文本生成器 AC自动机+DP
- [AC自动机+DP] bzoj 1030: [JSOI2007]文本生成器
- [AC自动机 DP] BZOJ 1030 [JSOI2007] 文本生成器
- 【bzoj 1030】 [JSOI2007]文本生成器(AC自动机+dp)
- 【BZOJ 1030】[JSOI2007]文本生成器 Ac自动机+fail树上dp
- BZOJ 1030 [JSOI2007] 文本生成器 AC自动机+DP
- BZOJ 1030: [JSOI2007]文本生成器 DP,AC自动机
- [BZOJ 1030][JSOI2007]文本生成器(AC自动机+DP)
- BZOJ 1030 [JSOI2007]文本生成器 DP+AC自动机
- 【BZOJ】1030 [JSOI2007]文本生成器 AC自动机+DP
- [BZOJ]1030: [JSOI2007]文本生成器 AC自动机+DP
- bzoj 1030: [JSOI2007]文本生成器(AC自动机+DP)
- BZOJ[1030][JSOI2007]文本生成器 AC自动机+dp
- 【AC自动机】【bzoj 1030】: [JSOI2007]文本生成器
- BZOJ 1030: [JSOI2007]文本生成器 AC自动机
- BZOJ 1030: [JSOI2007]文本生成器 AC自动机
- 1030: [JSOI2007]文本生成器 AC自动机+DP
- apache commons包简介
- 设计模式--类的关系
- 《林锐-高质量C/C++编程指南》笔记
- 几个SQL语句笔试题
- Linux内存占用情况分析
- bzoj 1030: [JSOI2007]文本生成器 (ac自动机上的dp)
- JSON和JSONP的区别,以及使用方法
- C# WPF设置窗口透明
- HDFS snapshot操作实战
- redis 获取字节码 反序列化
- [面试]努力方向和面试准备
- extjs4 combobox 默认选择
- linux系统的开机流程
- 表单验证封装类