其他分享
首页 > 其他分享> > [JSOI2007]文本生成器【AC自动机+DP】

[JSOI2007]文本生成器【AC自动机+DP】

作者:互联网

下定决心想要将这份爱意传达给你,与你在一起的每一刻总是那么值得珍藏,
你的存在左右着我的思绪,实在是不想错过这样的美好,
真的不和我在一起吗?
image

我的学术生涯,虽然有点奇妙,嗯,果然是开始了。导师是个副教授,叫我写\(vue\),嗯,也没问题,除了我一点也不会写\(vue\)之外。我从知网上下载他所有的论文时,忽然灵魂出窍灵光一现,想到一个海王见了都傻眼的点子。我的想法很大胆,我最近一直很大胆,不是不怕失败,不怕闯祸,不怕颜面尽失……只是,我渐渐明白了,只有肯在泥潭里打滚的野猪才能找到橡果。明天的任务就清晰了,一是学习\(vue\),二是研读手上的论文,三,最重要的,要给那几位教授发邮件轰炸了。我能预见我费心费力写的邮件可能被本校老师当做笑柄谈资,可能被外校老师一键删除,可是,我能预见,再也没有什么能阻止我了,就像我在开学前就加入\(ACM\)校队,就像我在军训前夕跌跌撞撞求加项目,就像我到武汉后就没有吃上一顿午饭,就像这个凌晨两点睡六点五十起床的日常……看吧,没有什么能阻止我。至于算法竞赛,我发现不觉间已更接近于深夜一种消遣了吧,就像春梦中的呓语。主动去追逐缥缈幻影里的鸿光吧,犯错的成本会越来越高的。标记好每个串的结尾点,跑AC自动机上按长度和节点方向\(DP\),求出不合法的情况数后容斥即可。

$click$ $for$ $codes$
# include "bits/stdc++.h"
using namespace std;
constexpr int N = 6003;
constexpr int mod = 1e4 + 7;
long long Pow(int x, int y) {
	long long ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod) if(y & 1) ans = ans * x % mod;
	return ans;
}
char str[N];
bool flag[N];
int ch[N][26], trie_index, fail[N];
struct Ahio_Corasick_Automation {
	void insert(char *str) {
		int len = strlen(str + 1), u = 0;
		for(int i = 1; i <= len; ++i) {
			int v = str[i] - 'A';
			if(!ch[u][v]) ch[u][v] = ++trie_index;
			u = ch[u][v];
		}
		flag[u] = true; // key 1
	}
	void build() {
		queue<int> q;
		for(int i = 0; i < 26; ++i) {
			if(ch[0][i]) {
				q.push(ch[0][i]);
			}
		}
		while(!q.empty()) {
			int u = q.front();
			q.pop();
			for(int i = 0; i < 26; ++i) {
				if(ch[u][i]) {
					fail[ch[u][i]] = ch[fail[u]][i];
					q.push(ch[u][i]);
					flag[ch[u][i]] |= flag[fail[ch[u][i]]]; // key 2
				} else {
					ch[u][i] = ch[fail[u]][i];
				}
			}
		}
	}
} AC;
long long f[N][N];
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i) {
		scanf("%s", str + 1);
		AC.insert(str);
	}
	AC.build();

	f[0][0] = 1; // key 3 // to assure length 1 -> val 1
	for(int i = 1; i <= m; ++i) {
		for(int j = 0; j <= trie_index; ++j) {
			if(flag[j]) continue;
			for(int k = 0; k < 26; ++k) {
				f[i][ch[j][k]] = (f[i][ch[j][k]] + f[i - 1][j]) % mod;
			}
		}
	}
	long long ans = Pow(26, m);
	for(int i = 0; i <= trie_index; ++i) {
		if(flag[i]) continue;
		ans = (ans - f[m][i] + mod) % mod;
	}
	printf("%lld", ans);
	return 0;
}

image

标签:AC,ch,JSOI2007,int,生成器,26,long,ans,fail
来源: https://www.cnblogs.com/bingoyes/p/16614777.html