1. 02最長子字符串
題目
牛牛有兩個(gè)字符串(可能包含空格),牛牛想找出其中最長的公共連續(xù)子串,希望你能幫助他,并輸出其長度。
例如:A = 4 B = 0 K = 30000 -> 1110 -> 1001 -> 0100 -> 1111
思路
動(dòng)態(tài)規(guī)劃。
兩個(gè)字符串從1增長到各自的長度。
memo[i][j]中記錄著,兩個(gè)字符串分別為i,j時(shí)的子字符串長度。
如果某個(gè)下標(biāo)對(duì)應(yīng)字符相同,那么memo[i][j]等于其memo[i-1][j-1]+1,也就是斜上一個(gè)+1。
否則,選取上面和前面中最大的(因?yàn)檫@兩個(gè)能增加到當(dāng)前兩個(gè)字符串,如果不同必然和上一個(gè)字符串的最長子字符串長度相同)。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
string commonStr(string &l,string &r)
{
int llen=l.size();
int rlen=r.size();
//memo[i][j]中存儲(chǔ)的是:第一個(gè)字符串長i,第二個(gè)長j時(shí)
//最長公共子字符串。
vector<vector<int>> memo(llen+1,vector<int>(rlen+1,0));
vector<vector<int>> memoPath(llen+1,vector<int>(rlen,0));
memo[0][0]=0;
for(int li = 1;li<=llen;li++)
{
for(int ri = 1;ri<=rlen;ri++)
{
//當(dāng)某個(gè)字符相等時(shí),標(biāo)記字符串長度比之前的+1;
if(l[li-1]==r[ri-1])
{
memo[li][ri]=memo[li-1][ri-1]+1;
memoPath[li][ri]=1;
//當(dāng)不同時(shí),選取,能夠達(dá)到ij長度的兩條子字符串的最長長度
//(i-1)j和i(j-1)這兩條字符串能夠到達(dá)ij
}else if(memo[li][ri-1]>memo[li-1][ri]){
memo[li][ri]=memo[li][ri-1];
memoPath[li][ri]=2;
}else{
memo[li][ri]=memo[li-1][ri];
memoPath[li][ri]=3;
}
}
}
for(auto i:memo)
{
cout<<endl;
for(auto j:i)
{
cout<<j<<" ";
}
}
cout<<endl;
int pathL=memoPath.size()-1;
int pathR=memoPath[0].size()-1;
string s;
while(pathL>0 && pathR>0)
{
if(memoPath[pathL][pathR] == 1)
{
s.push_back(l[pathL-1]);
pathL--;
pathR--;
}else if(memoPath[pathL][pathR] == 2)
{
pathR--;
}else{
pathL--;
}
}
reverse(s.begin(),s.end());
cout<<endl;
return s;
}
int main()
{
string l,r;
cin>>l>>r;
// l="bdcaba";
// r="abcbdab";
cout<<"result: "<<commonStr(l,r)<<endl;
}