最长公共子序列问题(Longest Common Subsequence)问题:
给定两个字符串A和B,求一个字符串,使得这个字符串是A和B的最长公共部分(子序列可以不连续)。
例:
sadstory adminsorry
公共子序列为"adsory",长度为6。
显然暴力解法复杂度在数据太大时无法承受,可以采用动态规划的方法进行编程。
令dp[i][j]表示A的i号位和B的j号位之前的LCS长度,字符串的下标从1开始,那么可以有两种决策方法:
- 如果A[i]==B[j],则字符串A和字符串B的LCS增加1,即dp[i][j]=dp[i-1][j-1]+1
- 如果A[i]!=B[j],则dp[i][j]会继承dp[i-1][j]和dp[i][j-1]中较大的长度
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100;
char A[maxn], B[maxn];
int dp[maxn][maxn];
int main()
{
int n;
gets(A + 1);
gets(B + 1);
int lenA = strlen(A + 1);
int lenB = strlen(B + 1);
//初始化
for (int i = 0; i < lenA; i++)
{
dp[i][0] = 0;
}
for (int i = 0; i < lenB; i++)
{
dp[0][i] = 0;
}
//状态转移方程
for (int i = 1; i <= lenA; i++)
{
for (int j = 1; j <= lenB; j++)
{
if (A[i] == B[j])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
printf("%d\n", dp[lenA][lenB]);
}
题目描述
给你一个序列X和另一个序列Z,当Z中的所有元素都在X中存在,并且在X中的下标顺序是严格递增的,那么就把Z叫做X的子序列。
例如:Z=<a,b,f,c>是序列X=<a,b,c,f,b,c>的一个子序列,Z中的元素在X中的下标序列为<1,2,4,6>。
现给你两个序列X和Y,请问它们的最长公共子序列的长度是多少?
输入
输入包含多组测试数据。每组输入占一行,为两个字符串,由若干个空格分隔。每个字符串的长度不超过100。
输出
对于每组输入,输出两个字符串的最长公共子序列的长度。
样例输入
abcfbc abfcab
programming contest
abcd mnp
样例输出
4
2
0
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 101;
string a, b;
char A[maxn], B[maxn];
int dp[maxn][maxn];
int main()
{
while (cin >> a >> b)
{
int lenA = a.length();
int lenB = b.length();
for (int i = 0; i < lenA; i++)
{
A[i + 1] = a[i];
}
for (int i = 0; i <= lenB; i++)
{
B[i + 1] = b[i];
}
//初始化
for (int i = 0; i <= lenA; i++)
{
dp[i][0] = 0;
}
for (int i = 0; i <= lenB; i++)
{
dp[0][i] = 0;
}
//状态转移方程
for (int i = 1; i <= lenA; i++)
{
for (int j = 1; j <= lenB; j++)
{
if (A[i] == B[j])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
printf("%d\n", dp[lenA][lenB]);
}
}