2021牛客暑期多校训练营5Double Strings(二维字符串dp)

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营5Double Strings(二维字符串dp)相关的知识,希望对你有一定的参考价值。

D Double Strings

题意:

  • 给出两个字符串A, B, 在其中选出两个等长的子序列(可以不连续)a, b,满足a的字典序严格小于b,求这样的方案有多少个,答案mod(1e9+7)

思路:

  • 好的方案的构成是“一段相同的前缀+一个不同字符(a比b小)+长度相同的任意后缀”。枚举不同的字符在两个序列中的位置。
  • 用dp[i][j]表示只考虑 A 中的前 i 个字符和 B 中的前 j 个字符时的相同的子序列的个数,转移可以 O(1),这样可以统计出相同的前缀个数,这部分是 O(|s|*|t|) 的。
  • 长度相同的任意后缀也可以用类似的 dp 计算,或者设 A 中此时剩余长度为 x, B 中剩余长度为 y,不失一般性地设 x≤y,现在要求的就是 ΣC(x,i)*C(y,i) = ΣC(x,x-i)*C(y,i) = C(x+y,x),这部分也是 O(|s|*|t|) 的。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
int n, m, slen, tlen;
char s[5010], t[5010];
int dp[5010][5010], f[5010][5010];
int main(){
	cin>>s+1>>t+1;
	slen=strlen(s+1), tlen=strlen(t+1);
	for(int i=1; i <= tlen; i++){
		for(int j=1; j <= slen; j++){
			dp[i][j]= (dp[i][j]+(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+mod)%mod)%mod;
			if(t[i]==s[j])dp[i][j]=(dp[i][j]+1LL+dp[i-1][j-1])%mod;
			f[i][j]=(f[i-1][j]+f[i][j-1])%mod;
			if(t[i]>s[j])f[i][j] = (f[i][j]+1LL+dp[i-1][j-1])%mod;
		}
	}
	cout<<f[tlen][slen]<<"\\n";
	return 0;
}


以上是关于2021牛客暑期多校训练营5Double Strings(二维字符串dp)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营4

2021牛客暑期多校训练营9

2021牛客暑期多校训练营3

2021牛客暑期多校训练营5

2021牛客暑期多校训练营1

2021牛客暑期多校训练营6