在上一篇已经讲述过最长公共非连续子序列计算公式为:
而对于最长公共连续子序列,实现的公式为:
比较后,将数据的比较结果存放到二维数组中:
实现代码为:时间复杂度和空间复杂度都是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);
}