Problem F: LCS

Problem F: LCS

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 0   Solved: 0

Description

   Giving two strings consists of only lowercase letters, find the LCS(Longest Common Subsequence) whose all partition are not less than k in length.

Input

There are multiple test cases. In each test case, each of the first two lines is a string(length is less than 2100). The third line is a positive integer k. The input will end by EOF.

Output

    For each test case, output the length of the two strings’ LCS.

Sample Input

abxccdef
abcxcdef
3
abccdef
abcdef
3

Sample Output

4
6

HINT

   In the first test case, the answer is:


      abxccdef


      abcxcdef


    The length is 4.


   In the second test case, the answer is:


      abccdef


      abc def


   The length is 6

解题思路:求俩字符串的最长公共子序列(要求每一段连续子串的长度>=k)

如样例1:

abxccdef

abcxcdef

最长公共子序列由ab+ccdef abc+cdef(或abx+cdef ab+xcdef)组成,因为子串ab长度小于3,故只取子串cdef,故最长公共子序列(子串长度>=k)长度为4

很明显,此题是最长公共子序列的变形,要解决此题,首先我们要理解简单版的最长公共子序列如何求解




Problem F: LCS_第1张图片

Problem F: LCS_第2张图片

作为变形,当s1[i-1]!=s2[j-1]时,我们不能再继承之前的maxLen值了,因为在这里发生了断裂,即这里开始不连续,故maxLen[i][j]=0;

待我们处理好maxLen[][]数组之后,我们才开始计算最长公共子序列(子串长度>=k)

令dp[i][j]表示s1的左边i个字符形成的子串,与s2左边的j个字符形成的子串的最长公共子序列的长度(i,j从0开始算,子串长度>=k)

我们可以得到转移方程


/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 2105;
const int M = 40;
const int inf = 100000000;
const int mod = 2009;
char s1[N],s2[N];
int maxLen[N][N],dp[N][N];
int main()
{
	int k,i,j,l1,l2;
    while(~scanf("%s",s1))
    {
    	scanf("%s",s2);
    	scanf("%d",&k);
    	l1=strlen(s1);
    	l2=strlen(s2);
    	for(i=0;i<=l1;i++)
    		maxLen[i][0]=0;
   		for(i=0;i<=l2;i++)
    		maxLen[0][i]=0;
   		memset(dp,0,sizeof(dp));
   		for(i=1;i<=l1;i++)
   			for(j=1;j<=l2;j++)
   				if(s1[i-1]==s2[j-1])
				   maxLen[i][j]=maxLen[i-1][j-1]+1;
			   	else
		   			maxLen[i][j]=0;
		/*for(i=1;i<=l1;i++)
		{
			for(j=1;j<=l2;j++)
   				printf("%d ",maxLen[i][j]);
			puts("");
		}
		puts("");*/
		for(i=1;i<=l1;i++)
   			for(j=1;j<=l2;j++)
   				if(maxLen[i][j]>=k)
   					dp[i][j]=max(dp[i-1][j-1]+1,dp[i-k][j-k]+k);
				else
					dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
	 	/*for(i=1;i<=l1;i++)
		{
			for(j=1;j<=l2;j++)
   				printf("%d ",dp[i][j]);
			puts("");
		}*/
	 	printf("%d\n",dp[l1][l2]);
    }
    return 0;
}

菜鸟成长记

你可能感兴趣的:(dp,ACM)