hdu 5282 Senior's String 两次dp

题链:http://acm.hdu.edu.cn/showproblem.php?pid=5282

Senior‘s String

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 142    Accepted Submission(s): 40

Problem Description

Xuejiejie loves strings most. In order to win the favor of her, a young man has two strings
X,
Y
to Xuejiejie. Xuejiejie has never seen such beautiful strings! These days, she is very happy. But Xuejiejie is missish so much, in order to cover up her happiness, she asks the young man a question. In face of Xuejiejie, the young man is flustered. So he asks
you for help.

The question is that :

Define the L
as the length of the longest common subsequence of
X
and Y.(
The subsequence does not need to be continuous

in the string, and a string of length L
has 2L
subsequences containing the empty string ). Now Xuejiejie comes up with all subsequences of length
L
of string X,
she wants to know the number of subsequences which is also the subsequence of string
Y.

Input

In the first line there is an integer
T,
indicates the number of test cases.

In each case:

The first line contains string X,
a non-empty string consists of lowercase English letters.

The second line contains string Y,
a non-empty string consists of lowercase English letters.

1≤|X|,|Y|≤1000,
|X|
means the length of X.

Output

For each test case, output one integer which means the number of subsequences of length
L
of X
which also is the subsequence of string Y
modulo 109+7.

Sample Input

2
a
b
aa
ab

Sample Output

1
2

中文题意:

学姐姐非常喜欢字符串,所以学弟送给了她两个字符串作为礼物。

两个字符串分别为X,Y。她非常开心,但在开心之余她还想考考学弟。

她定义L为X与Y的最长公共子序列的长度(子序列在字符串内不一定连续,一个长度为L的字符串有2L个子序列,包括空子序列)。

现在学姐姐取出了X的所有长度为L的子序列,并要求学弟回答在这些子序列中,有多少个是Y的子序列。

因为答案可能很大,所以学弟只需要回答最终答案模109+7。

官方题解:

wei里存的是Y串的前j个字母中,  26个字母最后出现在第几个(字符串下标+1)

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAX_N 1100//再大dp数组会爆的   O(n*m)
char a[MAX_N],b[MAX_N];
int dp[MAX_N+1][MAX_N+1];
int dd[MAX_N+1][MAX_N+1];//b前j个字母中  最后一个 与x[i]
int wei[MAX_N+1][26];//Y前i个字母中 最后一个j字母在的位置
__int64 f[MAX_N+1][MAX_N+1];

int mod=1e9+7;
int main()
{
	int n,m,tem,t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s%s",a,b);
		memset(dp,0,sizeof(dp));
		n=strlen(a);
		m=strlen(b);
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				if(a[i]==b[j])
			    	dp[i+1][j+1]=max(dp[i][j]+1,max(dp[i+1][j],dp[i][j+1]));
				else
					dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
			}
		}
		memset(wei,0,sizeof wei);
		for(int i=1;i<=m;i++)
		{
			for(int j=0;j<26;j++)
				wei[i][j]=wei[i-1][j];
			wei[i][b[i-1]-'a']=i;
		}
		memset(f,0,sizeof f);
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=m;j++)
			{
				if(dp[i][j]==0)
				{
					f[i][j]=1;
					continue;
				}
				if(dp[i-1][j]==dp[i][j])
					f[i][j]=(f[i][j]+f[i-1][j])%mod;
				int p=wei[j][a[i-1]-'a'];
				if(p)
				{
					if(dp[i-1][p-1]+1==dp[i][j])
						f[i][j]=(f[i][j]+f[i-1][p-1])%mod;
				}
			}
		}

		printf("%I64d\n",f[n][m]%mod);
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 5282 Senior's String 两次dp

时间: 2024-07-31 06:03:25

hdu 5282 Senior's String 两次dp的相关文章

[HDOJ - 5282] Senior&#39;s String 【DP】

题目链接:BZOJ - 5282 题目分析 LCS 就是用经典的 O(n^2) DP 解决,f[i][j] 表示 x 串前 i 个字符与 y 串前 j 个字符的 LCS 长度. f[i][j] = max(f[i - 1][j], f[i][j - 1]); if (x[i] == y[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1); 然后再设置一个状态 g[i][j], 表示 x 串的前 i 个字符中,有多少个长为 f[i][j] 的子序列同时也

HDU - 6086 Rikka with String AC自动机 + dp

HDU - 6086 前缀和后缀分别建AC自动机, 考虑从两端往中间dp dp[ o ][ i ][ j ][ mask ] 表示放了前面和后面o个, 第一个自动机在 i 位置, 第二个自动机在 j 位置, 拥有的目标串的状态是mask的方案数. 对于跨过两端的东西, 我们最后处理就好了. #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #def

hdu 3336 count the string(KMP+dp)

题意: 求给定字符串,包含的其前缀的数量. 分析: 就是求所有前缀在字符串出现的次数的和,可以用KMP的性质,以j结尾的串包含的串的数量,就是next[j]结尾串包含前缀的数量再加上自身是前缀,dp[i]表示以i为结尾包含前缀的数量,则dp[i]=dp[next[i]]+1,最后求和即可. #include <map> #include <set> #include <list> #include <cmath> #include <queue>

HUD5282 Senior&#39;s String 详解(使用DP解决组合数学)

题意:假设两个字符串的最长公共子序列长度为L,求第一个字符串中有多少个长度为L的子序列是第二个字符串的子序列.显然找出一个字符串的所有长度为L的子序列是组合数学问题,如果枚举所有子串的时间复杂度是n! 级的.这里就需要用动态规划来解决.首先用dp[i][j]和num[i][j]分别记录x的前I个字母和y的前j 个字母的最长公共子序列的长度和个数.先求出dp, 然后求num:.求num[i][j]分为两种情况,子序列不选x[i]和选x[i]: 1. 不选x[i]: 如果dp[i][j] == dp

HDU 5863 cjj&#39;s string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )

题目链接 题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数 分析 : 直觉是DP 不过当时看到 n 很大.但是 m 很小的时候 发现此题DP并不合适.于是想可能是某种组合数学的问题可以直接公式算 看到题解的我.恍然大悟.对于这种数据.可以考虑一下矩阵快速幂优化的DP 首先要想到线性递推的 DP 式子 最直观的想法就是 dp[i][j] = 到第 i 个位置为止.前面最长匹配长度为 j 的方案数 但是如果仔

HDU 4114 Disney&#39;s FastPass (状压DP)

题意:给定 n 个区域,然后给定两个区域经过的时间,然后你有 k 个景点,然后给定个每个景点的区域和有票没票的等待时间,从哪些区域能够得到票,问你从景点1开始,最后到景点1,而且要经过看完这k个景点. 析:一个状压DP,dp[s1][s2][i] 表示已经访问了 s1 中的景点,拥有 s2 的票,当前在 i 区域,然后两种转移一种是去下一个景点,另一种是去下一个区域拿票.当时输入,写错了,卡了好长时间.... 代码如下: #pragma comment(linker, "/STACK:10240

HDU 1503 Advanced Fruits (LCS,DP)

题意:给你两字符串s1,s2,用最短的字符串表示他们(公共字串输出一次). Sample Input apple peach ananas banana pear peach Sample Output appleach bananas pearch dp[i][j] : 第一个字符串的前 i 个 ,和第二个字符串的前 j 个最短组合的长度 . pre[i][j] : 第一个字符串的第 i 个 ,和第二个字符串的第 j 个字符的状态. #include<cstdio> #include<

HDU 4901 The Romantic Hero(二维dp)

题目大意:给你n个数字,然后分成两份,前边的一份里面的元素进行异或,后面的一份里面的元素进行与.分的时候按照给的先后数序取数,后面的里面的所有的元素的下标一定比前面的大.问你有多上种放元素的方法可以使得前面异或的值和后面与的值相等. dp[x][y] 表示走到第x步,得到y这个数字一共有多少种方法. 但是需要注意这里得分一下,不能直接用dp数组存种数,你需要分一下从上一层过来的次数,和这一层自己可以到达的次数.然后取和的时候前后两个集合的种数进行乘法,注意边乘边取余. 顺便给一组数据: 4 3

hdu 4865 Peter&#39;s Hobby(概率dp)

http://acm.hdu.edu.cn/showproblem.php?pid=4865 大致题意:有三种天气和四种叶子状态.给出两个表,分别是每种天气下叶子呈现状态的概率和今天天气对明天天气的概率.给出n天叶子的状态,输出最有可能的天气序列. 思路:wl[i][j]表示天气为i,叶子为j的概率,ww[i][j]表示今天天气为i明天天气为j的概率,st[i]表示第一天天气为i的概率. 对于叶子序列{a1,a2......an},存在一个天气序列{b1,b2......bn},那么总的概率g[