noip 2015 子串

给定两个字符串A,B(都是由a,b组成)(长度分别为n,m);你可以在A中任按顺序截取k个字串组成B,问能截取的个数

动态规划;

s[i][j][k]:数组A到第i项了,数组B到第j项了,总方案数;

f[i][j][k]:数组A到第i项了,数组B到第j项了,必须有A的第[i]项的总方案数;

当a[i]=b[j]时;

f[i][j][k]=f[i-1][j-1][k]+s[i-1][j-1][k-1];

s[i][j][k]=s[i-1][j-1][k]+f[i][j][k];

当a[i]!=b[j]时;

f[i][j][k]=0;

s[i][j][k]=s[i-1][j][k];

//注意-1超边界

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
#define fo(a,b,c)  for(int a=(b);a<=(c);a++)
const int mod=1000000007;
char a[1005],b[205];
int s[2][205][205],f[2][205][205],n,m,h;
void solve()
{
	int pre=1;
	int now=0;
	s[pre][0][0]=1;
	fo(i,0,n-1)
	{
		s[now][0][0]=1;
		fo(j,0,m-1)
		{
		fo(k,1,min(h,j))
		   if(a[i]==b[j])
			{	
				f[now][j][k]=(f[pre][j-1][k]+s[pre][j-1][k-1])%mod;
				s[now][j][k]=(f[now][j][k]+s[pre][j][k])%mod; 
			} 
			else
		      {s[now][j][k]=s[pre][j][k];
		      	   f[now][j][k]=0;
		      } 
		}
		pre^=1;
		now^=1;
	}
	cout<<s[pre][m-1][h]%mod;
}
int main()
{
	scanf("%d%d%d%s%s",&n,&m,&h,a,b);
    solve();	
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/Bluelanzhan/article/details/80207677