您的位置:首页 > 其它

LCS(最长公共子序列)dp模板,长度和打印子序列

2014-05-10 15:02 363 查看
参考博客和题目描述http://hzzy-010.blog.163.com/blog/static/79692381200872024242126/

【我的记忆化搜索和递推模版】

[INPUT]

GCCCTAGCG

GCGCAATG

[OUTPUT]

5

GCCTG

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 100
char a[MAXN], b[MAXN];
int lena, lenb, dp[MAXN][MAXN];//dp[i][j]记录字符串a[0~i-1]和字符串b[0~j-1]的最长子序列长度
struct NODE{
int x, y;
}f[MAXN][MAXN];
//f[i][j]记录dp[i][j]的父亲节点,也就是他是由max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+sum(当a[i-1] == b[j-1]时sum = 1,否则为0))继承下来的

//【记忆化】寻找两个字符串的最大子序列长度,并记录路径
int dfs(int i, int j)
{
if (-1 != dp[i][j])
return dp[i][j];
if (0 == i || 0 == j)
return dp[i][j] = 0;
if (a[i-1] == b[j-1])
{
dp[i][j] = dfs(i-1,j-1)+1;
f[i][j].x = i-1;
f[i][j].y = j-1;
}
else
{
int buf1 = dfs(i-1,j), buf2 = dfs(i,j-1);
if (buf1 < buf2)
dp[i][j] = buf2,f[i][j].x = i, f[i][j].y = j-1;
else
dp[i][j] = buf1, f[i][j].x = i-1, f[i][j].y = j;
}
return dp[i][j];
}
//【递推】
int sloved(int la, int lb)
{
memset(dp,0,sizeof(dp));
for (int i = 1; i <= la; i++)
{
for (int j = 1; j <= lb; j++)
{
if (a[i-1] == b[j-1])
dp[i][j] = dp[i-1][j-1]+1, f[i][j].x = i-1, f[i][j].y = j-1;
else if(dp[i-1][j] < dp[i][j-1])
{
dp[i][j] = dp[i][j-1];
f[i][j].x = i;
f[i][j].y = j-1;
}
else
{
dp[i][j] = dp[i-1][j];
f[i][j].x = i-1;
f[i][j].y = j;
}
}
}
return dp[la][lb];
}
//输出其中一个最长子序列
void printans(int i, int j)
{
if (!i || !j)
return;
int x = f[i][j].x, y = f[i][j].y;
printans(x, y);
if (dp[x][y]+1 == dp[i][j])
printf ("%c", a[i-1]);
}
int main ()
{
#ifdef SHY
freopen("e:\\1.txt", "r", stdin);
#endif
while(gets(a))
{
gets(b);
lena = strlen(a);
lenb = strlen(b);
memset(dp,-1,sizeof(dp));
printf ("%d\n", sloved(lena, lenb));
printans(lena, lenb);
printf ("\n");
}
return 0;
}


 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  模版 LCS