1. 程式人生 > >【動態規劃】LCS演算法:求兩字串最大公共字串(連續)

【動態規劃】LCS演算法:求兩字串最大公共字串(連續)

LCS演算法的應用

問題描述:求兩字串的連續最大公共子字串

思路:根據上文LCS演算法求解兩字串的最大公共子序列(不連續),可以得到求解連續子字串的啟示,如圖所示,構造LCS矩陣vec,將兩個字串按矩陣方式排開,矩陣中的每個元素vec[i][j]表示字串a的第i個字元和字串b的第j個字元是否相等。如圖1中所示。在斜對角線上,連續的1就表示兩字串對應位置連續相等。


最長的連續1就表示該子字串是最大公共子字串。分別找出對應的字元即可求出這個最長子串。如下圖1,有兩個最長的公共子字串。bab與aba.

我們可以對這個演算法進行改進,當前行列相等時,在其左上角值的基礎上+1,這樣就記錄了連續1的長度,如下圖2

 

再對演算法進行改進,可以發現,我們只需要知道最大值就知道最大公共子串的長度,而最大值的位置可以求出最大公共子串的結束位置,而求解這兩個資訊,使用一個矩陣是十分浪費空間的!實際上只需要一維陣列即可解決,在求當前行時,記錄上一行的值,並始終儲存最大值所在的位置(行或列),就可以求出結果。

程式碼如下:

string LCS_continuous(string str1,string str2)
{
	int i,j,maxnum=0,maxj=0;
	int n1=str1.size(),n2=str2.size();
	vector<int> last,cur,temp;//last、cur記錄上一行、當前行的LCS資訊,temp作為輔助陣列。
	for(i=0;i<n2+1;i++)//初始值:第0行第0列置0
	{
		last.push_back(0);
		cur.push_back(0);
	}
	temp=cur;
	for(i=1;i<=n1;i++)
    {
		cur=temp;//cur清零
        for(j=1;j<=n2;j++)
        {
            if(str1[i-1]==str2[j-1])
			{
                cur[j]=last[j-1]+1;
				if(cur[j]>maxnum)//更新最大值
				{
					maxnum=cur[j];
					maxj=j-1;//記錄最大值列號
				}
			}
        }
		last=cur;//把當前行資訊傳遞給last
    }
	return str2.substr(maxj-maxnum+1,maxnum);
}
相關參考:

http://blog.csdn.net/yebanxin/article/details/52186706

http://www.2cto.com/kf/201410/346523.html