1015: LCS
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 58 Solved: 26
[ Submit][ Status][ Web Board]
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
题目链接:http://acm.hzau.edu.cn/problem.php?id=1015
题意:求最长公共子序列,不过对序列还要加上每个部分长度要大于k的条件。即当且仅当子序列是连续的不小于k的子串时,其算符合条件的子序列。
解题思路:
动规。只需对经典的LCS算法做稍微的改动。
首先,需要记录两个序列相同的连续子串部分。rec[i, j]表示两个字符串a和b的以ai和bj结尾的两个连续子串的相同数目
然后,即进入动规部分。
dp[i, j]表示ai和bj的前缀中最大的符合条件的LCS。则有状态转移方程:
dp[i, j] = max(dp[i-1, j-1]+1, dp[i-k][j-k]+k), ai=bj and rec[i, j] >= k
dp[i, j] = max(dp[i-1, j], dp[i, j-1]) ai ≠ bj and rec[i, j] >= k
代码:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
char a[2300], b[2300];
int dp[2300][2300], tmp[2300][2300];
int main(){
int k;
while(scanf("%s%s%d", a+1, b+1, &k) != EOF){
memset(dp, 0, sizeof dp);
memset(tmp, 0, sizeof tmp);
int l1 = strlen(a+1), l2 = strlen(b+1);
if(k > min(l1, l2)){
printf("0\n");
continue;
}
for(int i = 1; i <= l1; i++){
for(int j = 1; j <= l2; j++){
if(a[i] == b[j]){
dp[i][j] = dp[i-1][j-1] + 1;
}
}
}
for(int i = 1; i <= l1; i++){
for(int j = 1; j <= l2; j++){
if(dp[i][j] >= k){
tmp[i][j] = max(tmp[i-1][j-1]+1, tmp[i-k][j-k] + k);
}
else tmp[i][j] = max(tmp[i-1][j], tmp[i][j-1]);
}
}
printf("%d\n", tmp[l1][l2]);
}
return 0;
}