LCS问题:
给定序列
X = <x1,x2,...,xn>
和另一个序列
Y = <y1,y2,...,ym>
找两个递增的下标序列
<i1, i2, ...ik> 和 <j1, j2, ..., jk>使
xi1 == yj1
xi2 == yj2
......
xik == yjk
令Z = <xi1, xi2,..., xik>,那么称Z是X和Y的一个公共子串,
LCS问题是求最长的公共子串,即最长的下标序列
动态规划解法:
令Xi表示X的前缀<x1,x2,...,xi>
c[]i[j] 表示Xi和Yi的LCS长度,动态规划的状态转移方程为:
如果xi == yj, c[i][j] = c[i-1][j-1] + 1
如果xi != yj, c[i][j] = max(c[i-1][j], c[i][j-1])
#include <stdio.h>
#include <string.h>
//#define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__)
#else
#define debug(...)
#endif
#define max(a,b) (a) > (b) ? (a) : (b)
#define N 250
int c[N][N];
int lcs(char *s1, char *s2)
{
int i, j, n, m;
n = strlen(s1);
m = strlen(s2);
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (s1[i-1] == s2[j-1]) {
c[i][j] = c[i-1][j-1] + 1;
}
else {
c[i][j] = max(c[i][j-1], c[i-1][j]);
}
debug("c[%d][%d] = %d\n", i, j, c[i][j]);
}
}
return c[n][m];
}
int main()
{
char s1[N], s2[N];
while (scanf("%s%s", s1, s2) != EOF) {
debug("%s %s\n", s1, s2);
printf("%d\n", lcs(s1, s2));
}
return 0;
}
本文介绍最长公共子序列(LCS)问题及其动态规划解法,通过两个序列寻找它们之间的最长公共子串,并提供了一段C语言实现的示例代码。
2098

被折叠的 条评论
为什么被折叠?



