最长连续公共子序列

在上一篇已经讲述过最长公共非连续子序列计算公式为:


而对于最长公共连续子序列,实现的公式为:


比较后,将数据的比较结果存放到二维数组中:


实现代码为:时间复杂度和空间复杂度都是O(m*n)

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


void longestComSubConstantSequce(string str1, string str2)
{
	int m=str1.length();
	int n=str2.length();

	int maxLen=0;
	int maxIdxX=0;
	int maxIdxY=0;

	stack<char> s;
	vector<vector<int>> vec(m+1, vector<int>(n+1, 0));

	for(int i=1; i<m+1; i++)
	{
		for(int j=1; j<n+1; j++)
		{
			if(str1[i-1]==str2[j-1])
			{
				vec[i][j]=vec[i-1][j-1]+1;
				if(maxLen<vec[i][j])//计算时,统计最长连续公共子序列的下标以及长度
				{
					maxLen=vec[i][j];
					maxIdxX=i;
					maxIdxY=j;
				}
			}
			else
				vec[i][j]=0;//主要区别
		}
	}
	for(int i=maxIdxX, j=maxIdxY; vec[i][j]>0; i--, j--)//最后根据
	{
		s.push(str1[i-1]);
	}
	while(!s.empty())
	{
		cout<<s.top()<<"\t";
		s.pop();
	}
	cout<<endl;
}

void main()
{
	string str1="lelowpworldsan";
	string str2="oknowworldss";
	longestComSubConstantSequce(str1, str2);
}

以上方法占用空间较大,这里采用O(N)空间实现:

//保证s1长度大于p1
void lcs(char * s1, char *p1){
	int len1=strlen(s1);
	int len2=strlen(p1);
	int comm_len=min(len1, len2);

	int curMaxIdx=-1;
	int maxLen=-1;
	vector<int> lastLine(comm_len, 0);
	vector<int> curLine(comm_len, 0);

	cout<<"\t";
	for(int i=0; i<len2; i++)
		cout<<p1[i]<<"\t";
	cout<<endl;

	for(int i=0; i<len1; i++){//这里需要保证len1>len2,否则会出错,除非定义curLine时,长度去两个字符串较长者
		cout<<s1[i]<<"\t";
		if(s1[i]==p1[0])
			curLine[0]=1;
		else
			curLine[0]=0;
		cout<<curLine[0]<<"\t";
		for(int j=1; j<len2; j++){
			if(s1[i]==p1[j]){
				curLine[j]=lastLine[j-1]+1;
				if(curLine[j]>maxLen){
					maxLen=curLine[j];
					curMaxIdx=j-maxLen+1;
				}
			}
			else{
				curLine[j]=0;
			}
			cout<<curLine[j]<<"\t";
		}
		cout<<endl;
		lastLine=curLine;
	}
	for(int i=curMaxIdx; i<curMaxIdx+maxLen; i++){
		cout<<p1[i];
	}
	cout<<endl;
}

void main()
{
	char * s1="helojworldss";
	char * p1="helworldss";
	lcs(s1, p1);
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值