字符串dp - WOJ#1223 子串

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_42557561/article/details/102746270

传送门


Analysis
  • 首先这个名字“字符串dp”就是我乱取的……反正在字符串上搞嘛
  • 第二次做,在知道这是dp的情况下,依旧没有分析出来。。在大致瞥了一眼定义后,仍旧没有转移对。菜是十大原罪之首

考虑两个字符串
一般都需要在状态中记录下当前分别在各个串的哪个位置
那么前两维我们就定义出来了
f [ i ] [ j ] f[i][j] 表示在A串中进行到前i位,B串进行到前j位

等等,这样的定义很不明确
侯神说dp状态定义一定要尽量明确
什么叫做进行?
换一个
匹配到B串的第j位

再考虑题目中的信息,我们还需要记录提取出了几个串
加一维[k]表示提取出了k个串

最后考虑转移
由于串是要连续的,所以在转移的时候我们得知道上一个位置选没有
oh,再加一维[0/1](反正只要需要就加加加加)

综上所述,我们定义出来的状态长这样:
f [ i ] [ j ] [ k ] [ 2 ] f[i][j][k][2]

转移嘞?
如果 i i 这个位置不选。
f [ i ] [ j ] [ k ] [ 0 ] = f [ i 1 ] [ j ] [ k ] [ 0 ] + f [ i 1 ] [ j ] [ k ] [ 1 ] f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]
如果 i i 这个位置要选,肯定得满足 a [ i ] = = b [ j ] a[i]==b[j]
f [ i ] [ j ] [ k ] [ 1 ] = f [ i 1 ] [ j 1 ] [ k ] [ 1 ] + f [ i 1 ] [ j 1 ] [ k 1 ] [ 1 ] + f [ i 1 ] [ j 1 ] [ k 1 ] [ 0 ] f[i][j][k][1]=f[i-1][j-1][k][1]+f[i-1][j-1][k-1][1]+f[i-1][j-1][k-1][0]

哈哈,完啦

等等,好像空间开不下??(应该能过)
滚动一发,噢啦
(如果要滚动,记得枚举顺序反一下。因为要调用之前的信息)

还有一种没有记0/1状态的定义
其实本质是一样的就是看当前这一位 a [ i ] a[i] b [ j ] b[j] 相等的时候,是否独成一串

Code
#include<bits/stdc++.h>
using namespace std;
inline char nc(){
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define nc getchar
inline int read(){
	int x=0,f=1;
	char ch=nc();
	while(!isdigit(ch)&&ch!='-')ch=nc();
	if(ch=='-')ch=nc(),f=-1;
	while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-48;ch=nc();}
	return x*f;
}
const int N=1002,M=202;
typedef long long ll;
const int mod=1e9+7;
ll dp[M][M][2];
int n,m,k;
char a[N],b[M];
int  main(){
	n=read();m=read();k=read();
	scanf("%s",a+1);
	scanf("%s",b+1);
	dp[0][0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=m;j>=1;j--){
			if(a[i]!=b[j]){
				for(int l=0;l<=k;l++){
					dp[j][l][0]=(dp[j][l][0]+dp[j][l][1])%mod;
					dp[j][l][1]=0;
				}
			}
			else{
				dp[j][0][0]=(dp[j][0][0]+dp[j][0][1])%mod;
				for(int l=k;l>=1;l--){
					dp[j][l][0]=(dp[j][l][0]+dp[j][l][1])%mod;
					dp[j][l][1]=(dp[j-1][l-1][0]+dp[j-1][l-1][1]+dp[j-1][l][1])%mod;
				}
			}
		}
  	printf("%lld",(dp[m][k][0]+dp[m][k][1])%mod);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/102746270
今日推荐