最长公共序列LCS

图片来自https://www.jianshu.com/p/096c945be66b

注意:
1)如上图表格,字符串的第i个字符在逻辑上是c[i,j]中的i。
但是,在物理存储上存储在i-1(下标位置)
for (int i = 1; i <= len1; i++) {
			for (int j = 1; j <= len2; j++) {
				if (m_str1[i-1] == m_str2[j-1])//attention!!!
2)打印时采用回溯法,故采用栈先进后出(或者数组存放,倒序输出)
回溯的逻辑
if (在各自的当前位置处字符相同) {
		字符入栈;各自回退一步;
}else if(m_comlen[l1 - 1][l2] == m_comlen[l1][l2 - 1])//两条路均可选一条
					l1--;
 else if(m_comlen[l1-1][l2] < m_comlen[l1][l2 - 1])//选来时的路,较大的方向
					l2--;
 else
					l1--;
			
			
#pragma once

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

const unsigned int MAXSIZE = 101;


class Lcs
{
public:
	Lcs(){}
	Lcs(string s1,string s2):m_str1(s1),m_str2(s2) {
		init();
	}
	~Lcs(){}

	void init() {
		int len1 =m_str1.size(),len2= m_str2.size();
		for (int i = 0,j=0; i <=len1,j<=len2; i++,j++) {
			m_comlen[i][0] = m_comlen[0][j] = 0;
		}

		for (int i = 1; i <= len1; i++) {
			for (int j = 1; j <= len2; j++) {
				if (m_str1[i-1] == m_str2[j-1])//attention!!!
					m_comlen[i][j] = m_comlen[i - 1][j - 1] + 1;
				else {
					m_comlen[i][j] =
						max(m_comlen[i - 1][j],
							m_comlen[i][j - 1]);
				}
			}
		}

		/*
		for (int i = 0; i <= len1; i++) {
			for (int j =0; j <= len2; j++) {
				cout << m_comlen[i][j] << " ";
			}
			cout << endl;
		}
		*/
	}

	void getLCS() {
		int l1 = m_str1.size(), l2 = m_str2.size();
		stack<char> s;

		while (m_comlen[l1][l2]) {
			if (m_str1[l1-1] == m_str2[l2-1]) {
				s.push(m_str2[l2-1]);
				l1--;
				l2--;
			}else if (m_comlen[l1 - 1][l2] == m_comlen[l1][l2 - 1])
					l1--;
			else if (m_comlen[l1-1][l2] < m_comlen[l1][l2 - 1])
					l2--;
			else
					l1--;
		}
		

		while (!s.empty()) {
			cout << s.top(); s.pop();
		}
		cout << endl;
	}
private:
	string m_str1,m_str2;
	int m_comlen[MAXSIZE][MAXSIZE];
};


void testLcs() {
	string s1 = "ihaveapple", s2 = "ihasapp";
	Lcs test(s1, s2);
	test.getLCS();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值