LCS算法

1. 问题

查找两个序列的最长公共子序列
最长公共子序列的结构有如下表示:
设序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一个最长公共子序列Z=<z1, z2, …, zk>,
则:
若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;
若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。
其中Xm-1=<x1, x2, …, xm-1>,Yn-1=<y1, y2, …, yn-1>,Zk-1=<z1, z2, …, zk-1>。

2. 解析

我采用的两个序列为
S1 = <GCCCTAGCGDE>
S2 = <GCGCAATGDE>
为了用动态编程有效地计算 LCS,首先需要构建一个表格,用它保存部分结果。沿着顶部列出一个序列,再沿着左侧从上到下列出另一个序列。
1.先建立一张表格
在这里插入图片描述

2.初始化表示,将第一行和第一列全部设为0
在这里插入图片描述

3.填充表格(箭头表示回溯,即这次结果可以作为下次的已知条件利用)
在这里插入图片描述

4.通过这种回溯方法,得到的 LCS 为 GCCAG

3. 设计

string LCS(string s1, string s2)
{
	if (s1 == "" || s2 == "")
		return "";
	int m = s1.size() + 1;
	int n = s2.size() + 1;
	int lcs[m][n], i, j;
	for (i = 0; i < m; i++)
		for (j = 0; j < n; j++)
			lcs[i][j] = 0;
	for (i = 1; i < m; i++)
		for (j = 1; j < n; j++)
		{
			if (s1[i - 1] == s2[j - 1])
				lcs[i][j] = lcs[i - 1][j - 1] + 1;
			else
				lcs[i][j] = lcs[i - 1][j] >= lcs[i][j - 1] ? lcs[i - 1][j] : lcs[i][j - 1];//取上面或左侧最大值
		}
	i = m - 2;
	j = n - 2;
	string ss = ""
		while (i != -1 && j != -1)
		{
			if (x[i] == y[j])
			{
				ss += s[i];
				i--;
				j--;
			}
			else
			{
				if (lcs[i + 1][j + 1] == lcs[i][j])
				{
					i--;
					j--;
				}
				else
				{
					if (lcs[i][j + 1] >= lcs[i + 1][j])
						i--;
					else
						j--;
				}
			}
		}
	reverse(ss);//逆转ss
	return ss;
}

4. 分析

时间复杂度O(n)=mn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值