【BZOJ 1030】【JSOI 2007】文本生成器 AC自动机+递推

一直不理解到底怎么做啊,想了好久$TwT$

最后终于明白了为什么找到第一个满足条件的$fail$就计算,因为避免重复,这个回答,,,

然后$root$下面要接上26个节点,这里26个字母中不在字典内的都用$f[i][0]$代替了,这个也想了好久,$==$我还是回家种地吧。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mo 10007
#define N 103
#define M 6003
using namespace std;
int q[M], c[M][26], w[M], fail[M], f[N][M], n, m, cnt = 0;
inline void ins(char *s) {
	int len = strlen(s), now = 0;
	for(int i = 0; i < len; ++i) {
		int t = s[i] - ‘A‘;
		if (!c[now][t])
			c[now][t] = ++cnt;
		now = c[now][t];
	}
	w[now] = 1;
}
inline void BFS() {
	int head = 0, tail = 1, now = 0;
	q[1] = 0;
	while (head != tail) {
		now = q[++head];
		for(int t = 0; t < 26; ++t)
			if (c[now][t]) {
				q[++tail] = c[now][t];
				if (now == 0) continue;
				int tmp = fail[now];
				while (tmp && !c[tmp][t])
					tmp = fail[tmp];
				fail[c[now][t]] = c[tmp][t];
				if (w[c[tmp][t]])
					w[c[now][t]] = 1; //!!!!!!!
			}
	}
}
inline int ipow(int x, int nn) {
	int ans = 1;
	for(int t = x; nn; nn >>= 1, t = (t * t) % mo)
		if (nn & 1) {
			ans = (ans * t);
			if (ans >= mo)
				ans = ans % mo;
		}
	return ans;
}
inline void AC() {
	f[0][0] = 1;
	for(int i = 0; i <= m; ++i)
		for(int j = 0; j <= cnt; ++j)
			if (f[i][j]) {
				for(int t = 0; t < 26; ++t) {
					int tmp = j;
					while (tmp && !c[tmp][t])
						tmp = fail[tmp];
					tmp = c[tmp][t];
					if (!w[tmp]) {
						f[i + 1][tmp] += f[i][j];
						if (f[i + 1][tmp] >= mo)
							f[i + 1][tmp] %= mo;
					}
				}
			}
	int _ = 0, al = ipow(26, m);
	for(int i = 0; i <= cnt; ++i)
		if (!w[i]) {
			_ += f[m][i];
			if (_ > mo)
				_ %= mo;
		}
	int ans = ((al - _) % mo + mo) %mo;
	printf("%d\n", ans);
}
int main() {
	scanf("%d%d", &n, &m);
	char s[N];
	for(int i = 1; i <= n; ++i)
		scanf("%s", s), ins(s);
	BFS();
	AC();
	return 0;
}

最后终于做出来了,因为看了别人的模板,这也,,,

时间: 2024-11-06 18:06:52

【BZOJ 1030】【JSOI 2007】文本生成器 AC自动机+递推的相关文章

BZOJ 1030 JSOI 2007 文本生成器 AC自动机+DP

题目大意:给出一些字符串.已知如果文章里出现过这些字符串中的一个,那么就说这个文章是可读的.问长度为l的文章有多少是可读的文章. 思路:直接处理不太好弄, 我们可以统计出来不可读的文章,然后用26^l减去就是可读的文章总数. 将所有的字串建Trie图,然后设f[i][j]为文章的第i个字符Trie图中的第j个节点的时候不可读的文章的数量.转移就很简单了.注意一下取模就行了. CODE: #include <queue> #include <cstdio> #include <

BZOJ 1030: [JSOI2007]文本生成器( AC自动机 + dp )

之前一直没调出来T^T...早上刷牙时无意中就想出错在哪里了... 对全部单词建AC自动机, 然后在自动机上跑dp, dp(i, j)表示匹配到了第i个字符, 在自动机上的j结点的方案数, 然后枚举A~Z进行转移. -------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; #define idx(c) ((c) -

【BZOJ-1030】文本生成器 AC自动机 + DP

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3253  Solved: 1330[Submit][Status][Discuss] Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完

[JSOI2007][BZOJ1030] 文本生成器|AC自动机|动态规划

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2609  Solved: 1074[Submit][Status][Discuss] Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完

【BZOJ 1030】 [JSOI2007]文本生成器

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2017  Solved: 834 [Submit][Status] Description JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章-- 也就是说,生成的文章中每个字节都是完全随机

bzoj1030 文本生成器(AC自动机+dp)

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4777  Solved: 1986[Submit][Status][Discuss] Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完

【BZOJ1030】[JSOI2007]文本生成器 AC自动机+动态规划

[BZOJ1030][JSOI2007]文本生成器 Description JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章-- 也就是说,生成的文章中每个字节都是完全随机的.如果一篇文章中至少包含使用者们了解的一个单词,那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串).但是,即使按照这样的标准

[BZOJ1030] [JSOI2007] 文本生成器 (AC自动机 &amp; dp)

Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完全随机的.如果一篇文章中至少包含使用者们了解的一个单词,那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串).但是,即使按照这样的标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全

bzoj1030 [JSOI2007]文本生成器——AC自动机+DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1030 求至少有一个单词的文本串不太好求,所以转化成求所有情况减去没有一个单词的文本串: 没有一个单词的文本串可以用AC自动机+DP求,设 f[i][j] 表示文本串长度为 i ,当前 Trie 树上节点为 j 的方案数: 则 f[i][j] 可以转到仍然不包含单词的它的儿子的方案数中,同时文本串长度+1: 所以需要在 getfail 时把单词结尾的属性也转移一下,因为 fail 是单词结尾