不包含任何模式串的字符串个数

题目描述

生成一个长度为 \(n\),字符集为 \(\Sigma\) 的字符串 \(S\) .

给定若干模式串 \(s_{1\dots m}\),要求 \(S\) 中不能有任何一个子串为模式串 .

问字符串 \(S\) 的个数 .

答案对 \(P\) 取模,\(P\) 不超过 \(2^{31}\) .

数据范围:

\(|\Sigma|\le 10\) .

咋做

首先建出模式串的 AC 自动机(不妨记转移函数为 \(trans\)) .

考虑 DP,令 \(dp_{i,j}\) 表示串长为 \(i\),在 AC 自动机上走到编号为 \(j\) 的节点的合法串个数 .

则在 AC 自动机上走一步即可完成转移:

\[\large dp_{i+1, trans(j, c)} = \sum dp_{i,j}\qquad (c\in\Sigma) \]

暴力 DP,时间复杂度 \(O(|\Sigma|n\sum|s|)\) .

大概这么写:

dp[0][0] = 1;
for (int i=0; i<n; i++)
	for (int j=0; j<=cc; j++)
		for (int k=0; k<Sig; k++)
			if (!mark[tr[j][k]]) dp[i+1][tr[j][k]] = (dp[i+1][tr[j][k]] + dp[i][j]) % P;

Task 1 完美解决 .

然而我们发现 \(i\) 这个玩意和内层转移几乎没关系,只是为了保证转移顺序 .

也就是说这玩意相当于进行了 \(i\) 次内层转移,\(i\) 一维枚举根本没用 .

所以我们构建出内层转移矩阵,然后快速幂即可 .

设 AC 自动机大小为 \(c\),则 DP 部分时间复杂度为 \(O(c^3\log n)\) .

Task 2 完美解决 .

posted @ 2022-03-18 11:19  yspm  阅读(84)  评论(0)    收藏  举报
😅​