[NOIpTG2015]子串——[計數DP]

在這裏插入圖片描述
【題意分析】

這種dp題也就是按照套路來,先設一個四維的狀態:dp[i][j][k][l]就是第一個串前i個,第二個串前j個,取了k段,第二個串當前位置取不取(0不取1取)的方案總數

計數dp嘛,分類討論:

如果枚舉的位置兩個字符相同,那麼就表明可以取或不取

dpi,j,k,0=dpi1,j,k,0+dpi1,j,k,1dp_{i,j,k,0}=dp_{i-1,j,k,0}+dp_{i-1,j,k,1}

dpi,j,k,1=dpi1,j1,k1,1+dpi1,j1,k1,0+dpi1,j1,k,1dp_{i,j,k,1}=dp_{i-1,j-1,k-1,1}+dp_{i-1,j-1,k-1,0}+dp_{i-1,j-1,k,1}

//對第二個naive方程的解釋:這個字符取了,可能上個字符取了,連成一段或者另起一段,或者上個字符不取,那麼必定另起一段。

如果不同,那麼就只能不取

dpi,j,k,0=dpi1,j,k,0+dpi1,j,k,1dp_{i,j,k,0}=dp_{i-1,j,k,0}+dp_{i-1,j,k,1}

dpi,j,k,1=0dp_{i,j,k,1}=0

就好了,然後很明顯第一維可以滾動掉(大部分計數dp都可以滾動掉一維),就可以過了

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 1010
#define MAXM 205
#define qy 1000000007
using namespace std;

char s1[MAXN], s2[MAXN];
int dp[2][MAXM][MAXM][2], n, m, K, now, pre;

int main () {
	scanf ("%d%d%d", &n, &m, &K), scanf ("%s", s1 + 1), scanf ("%s", s2 + 1);
	dp[0][0][0][0] = dp[1][0][0][0] = 1, now = 0, pre = 1;
	for (register int i = 1; i <= n; i++) {
		now ^= 1, pre ^= 1;
		for (register int j = 1; j <= m; j++)
			for (register int k = 1; k <= K; k++) {
				if (s1[i] == s2[j]) {
					dp[now][j][k][0] = (dp[pre][j][k][0] + dp[pre][j][k][1]) % qy;
					dp[now][j][k][1] = ((dp[pre][j - 1][k - 1][0] + dp[pre][j - 1][k - 1][1]) % qy + dp[pre][j - 1][k][1]) % qy;
				}
				else {
					dp[now][j][k][0] = (dp[pre][j][k][0] + dp[pre][j][k][1]) % qy;
					dp[now][j][k][1] = 0;
				}
			}
	}
	return printf ("%d\n", (dp[n & 1][m][K][0] + dp[n & 1][m][K][1]) % qy), 0;
}
發佈了100 篇原創文章 · 獲贊 94 · 訪問量 6527
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章