2015D2T2 子串

2015D2T2 子串

problem

给定两个小写英文字母串\(A,B\),从\(A\)中取出\(k\)个子串按照先后顺序连接得到新的字符串。求可以使新串和\(B\)相等的方案数。答案对\(10^9+7\)取模。

solution

\(f(i,j,k)\)表示A串前i个字符里,使用了k个子串,来匹配了B串前j个字符。
可列出方程\(f(i,j,k)=f(i-1,j-1,k-1)+f(i-1,j-1,k)\),即为A串前i个字符里,使用了k个子串,匹配了B串前j个字符的方案数,等价于单独使用第i-1个字符作为一个子串的方案数和不单独使用的方案数
但是我们要考虑到使用和不使用,这个就涉及到0/1的这一维。所以我们添加0/1维,来表示使用了当前字符和没使用当前的字符。

转移方程

\[f(i,j,k,0)=f(i-1,j,k,0)+f(i-1,j,k,1) \]

如果第i位不使用
第i-1位未使用时,前i-1位匹配前j位使用k个子串
第i-1位使用时,前i-1位匹配前j位使用k个子串

\[[a_i=b_j]f(i,j,k,1)=f(i-1,j-1,k-1,0)+f(i-1,j-1,k,1)+f(i-1,k-1,k-1,1) \]

如果第i位使用,即a[i]==b[j]

  1. 第i-1位未使用而第i位作为一个新子串
  2. 第i位和前面连在一起,不单独使用
  3. 第i-1位使用了,但第i位仍作为一个新子串。

边界条件

对于A子串前i位,匹配B串第1个字符,那么只可能使用1个字符串,这种情况如果第i位不进行匹配,那么方案数就是之前所有能与第1位匹配的字符,所以

\[f(i,1,1,0)=\sum\limits_{i=1}^{n-1}[a_i=b_1] \]

同上,但如果B串第一位和A串第一位匹配了话,那么

\[f[i][1][1][1]=1 \]

是显然的。

总结

\[f(i,j,k,0)=f(i-1,j,k,0)+f(i-1,j,k,1) \]

\[[a_i=b_j]f(i,j,k,1)=f(i-1,j-1,k-1,0)+f(i-1,j-1,k,1)+f(i-1,k-1,k-1,1) \]

\[f(i,1,1,0)=\sum\limits_{i=1}^{n-1}[a_i=b_1] \]

\[f[i][1][1][1]=1 \]

维度优化

方程里只有i和i-1被来回调用,其余例如i-2,i-3在接下来的动态规划里是不需要的,可以把数组滚动起来。设置一个t1,t2变量分别是0,1,来回变换。最后交换的时候记得清零。

code

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
long long read(){
	int a=0,op=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9'){a*=10,a+=c^48,c=getchar();}
	return a*op;
}
const int maxn=1005;
const int mod=1e9+7;
char a[maxn],b[maxn];
long long n,m,k;
long long dp[2][201][201][2],s,t1,t2=1;
int main(){
	n=read(),m=read(),k=read();
	scanf("%s%s",a+1,b+1);
	for(int i=1;i<=n;i++){
		swap(t1,t2);
		dp[t1][1][1][0]=s;
		if(a[i]==b[1]) dp[t1][1][1][1]=1,s++;
		for(int j=2;j<=m;j++){
			for(int u=1;u<=k;u++){
				if(a[i]==b[j]) dp[t1][j][u][1]=((dp[t2][j-1][u-1][1]+dp[t2][j-1][u][1])%mod+dp[t2][j-1][u-1][0])%mod;
				dp[t1][j][u][0]=(dp[t2][j][u][0]+dp[t2][j][u][1])%mod;
			}
		}
		for(int j=1;j<=m;j++) for(int u=1;u<=k;u++) dp[t2][j][u][1]=dp[t2][j][u][0]=0;
	}
	printf("%lld",(dp[t1][m][k][1]+dp[t1][m][k][0])%mod);
	return 0;
}
posted @ 2020-10-15 10:05  刘子闻  阅读(66)  评论(0编辑  收藏  举报