题目传送门


思路

状态设计

像这种字符串匹配的题,状态设计里一定有一维代表目前匹配到了第 i i i 位。
所以,我们设 d p i , j dp_{i, j} dpi,j 表示目前 T T T 串已经匹配到了第 i i i 位,且匹配的 S S S 串的状态为 j j j

状态转移

假设现在状态为 j j j,我们就枚举下一个位置 T i + 1 T_{i + 1} Ti+1 的可能的字符,然后看看有哪些 S S S 串能匹配上。
假设能匹配的字符串的状态为 x x x,那么我们就可以转移 d p i + 1 , j   &   x + = d p i , j dp_{i + 1, j \ \& \ x} += dp_{i, j} dpi+1,j & x+=dpi,j
这里 j   &   x j \ \& \ x j & x 的意思就是,当前已经匹配第 i i i 位的字符串中,还有哪些可以匹配上第 i + 1 i + 1 i+1 位。

边界状态

边界状态是 d p 0 , 2 n − 1 = 1 dp_{0, 2 ^ n - 1} = 1 dp0,2n1=1
那么为什么边界不是 d p 0 , 0 = 1 dp_{0, 0} = 1 dp0,0=1 呢?
因为如果由 0 0 0 作为初始状态的话 0   &   x 0 \ \& \ x 0 & x 会一直为 0 0 0,转移不到下一个状态。

答案统计

只需要枚举所有状态,然后看看有哪些状态中 1 1 1 的个数恰好为 k k k,那就加入答案

时间复杂度

O ( T × 26 × 2 n × ∣ S ∣ ) O(T \times 26 \times 2 ^ n \times |S|) O(T×26×2n×S)


代码

#include <bits/stdc++.h>

using namespace std;

const int maxn = 15 + 7;
const int maxs = (1 << 15) + 7;
const int mod  = 1000003;

int T, n, m, ns, len;
char s[maxn][57];
int mch[57][30];
int dp[57][maxs];
void solve() {
	memset(mch, 0, sizeof(mch));
	memset(dp, -1, sizeof(dp));  // 初始化成 -1, 因为一些状态可能转移不到 
	scanf("%d%d", &n, &m);
	ns = (1 << n) - 1;
	for (int i = 1; i <= n; ++i)
		scanf("%s", s[i] + 1);
	len = strlen(s[1] + 1);
	
	// 初始化一下, 看看第 i 位的字符为 ch 时能匹配的 S 串的状态
	for (int i = 1; i <= len; ++i)
		for (int ch = 1; ch <= 26; ++ch)
			for (int j = 1; j <= n; ++j)
				if (s[j][i] - 'a' + 1 == ch || s[j][i] == '?')
					mch[i][ch] |= 1 << (j - 1);
	
	dp[0][ns] = 1;
	for (int i = 0; i < len; ++i) {
		for (int s = 0; s <= ns; ++s) {
			if (dp[i][s] == -1) continue;
			for (int ch = 1; ch <= 26; ++ch) {
				int nxt = (s & mch[i + 1][ch]);
				if (dp[i + 1][nxt] == -1) dp[i + 1][nxt] = 0;
				dp[i + 1][nxt] = (dp[i + 1][nxt] + dp[i][s]) % mod;
			}
		}
	}
	
	int ans = 0;
	for (int s = 0; s <= ns; ++s) {
		int cntbit = 0;
		for (int i = 0; i < n; ++i)
			if (s & (1 << i)) ++cntbit;
		if (cntbit == m && dp[len][s] != -1)
			ans = (ans + dp[len][s]) % mod;
	}
	printf("%d\n", ans);
}
int main() {
	scanf("%d", &T);
	while (T--) solve();
	return 0;
}
Logo

集算法之大成!助力oier实现梦想!

更多推荐