一 问题描述
最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。
其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
比如,序列{a , b , c , b , d , a , b} 和 {b , d , c , a , b , a}的最长公共子序列为{b, d, a, b},长度为4
二 算法
假定两个序列是s1和s2,定义c[i][j]为 s1 的前i个序列 与 s2 的前j个序列的最长公共子序列长度。
那么有:
- 如果s1[i] == s2[j],c[i][j] = c[i-1][j-1];
- 否则,c[i][j] = max{c[i-1][j], c[i][j-1]};
三 代码
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
int c[1002][1002];
int main()
{
string s1;
string s2;
while (cin >> s1 >> s2)
{
size_t i,j;
for (i = 0; i < s1.length(); ++i)
{
for (j = 0; j < s2.length(); ++j)
{
if (s1[i] == s2[j])
c[i+1][j+1] = 1 + c[i][j];
else
c[i+1][j+1] = max(c[i][j+1], c[i+1][j]);
}
}
cout << c[i][j] << endl;
}
return 0;
}
#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <limits.h>
#include <assert.h>
using namespace std;
int c[100][100];
char f[100][100];
void print(char arr[][100], string s, int i, int j)
{
if (i == -1 || j == -1)
return;
if (arr[i][j] == 'E')
{
print(arr, s, i-1, j-1);
cout << s[i];
} else if (arr[i][j] == 'L')
{
print(arr, s, i, j-1);
} else
{
print(arr, s, i-1, j);
}
}
int main()
{
int i,j;
string s1="abcd";
string s2 = "abbd";
for (i = 0; i < s1.length(); ++i)
for (j = 0; j < s2.length(); ++j)
{
if (s1[i] == s2[j])
{
c[i+1][j+1] = c[i][j] + 1;
f[i][j] = 'E';
}
else
{
if (c[i+1][j] > c[i][j+1])
{
c[i+1][j+1] = c[i+1][j];
f[i][j] = 'L';
}
else
{
c[i+1][j+1] = c[i][j+1];
f[i][j] = 'U';
}
}
}
cout << c[i][j] << endl;
print(f, s1, i-1, j-1);
return 0;
}