[動態規劃]最長公共子串長度問題

題目來自於2014.8.29阿里在線筆試題:給定一個query和一個text,均由小寫字母組成。要求在text中找出以同樣的順序連續出現在query中的最長連續字母序列的長度。例如, query爲“acbac”,text爲“acaccbabb”,那麼text中的“cba”爲最長的連續出現在query中的字母序列,因此,返回結果應該爲其長度3。請注意程序效率。


仔細分析這道題,發現就是求query和text的最長公共子串長度,是經典的動態規劃問題。

F(i,j)表示以query[i]和text[j]爲結尾的公共子串長度,如果query[i]!=text[j],即兩個字符不等,顯然不會有以兩者爲共同結尾的子串,因此F(i,j)=0;如果query[i]==text[j],即兩個字符相等,就應該判斷兩者前一個字符是否相等,如果不等則說明只有這兩個字符是公共子串,因此F(i,j)=1,如果相等,公共子串長度應爲前一個字符的公共子串長度加1,因此F(i,j)=F(i-1,j-1)+1。

綜上可知狀態轉移方程爲:

F(i,j) = 0                ( query[i]!=text[j] )

        = F(i-1,j-1)+1 (query[i]==text[j] )

實際編程時,可開闢Q*T大小的二維數組存儲計算結果,再從所有結果中取出最大值即可。

複雜度分析:Q爲query長度,T爲text長度,需要把每個字符兩兩進行比較,時間複雜度爲O(Q*T),需要存儲所有字符的比較結果,空間複雜度爲O(Q*T)

代碼如下:

/*
給定一個query和一個text,均由小寫字母組成。要求在text中找出以同樣的順序連續出現在
query中的最長連續字母序列的長度。例如, query爲“acbac”,text爲“acaccbabb”,那麼text
中的“cba”爲最長的連續出現在query中的字母序列,因此,返回結果應該爲其長度3。請注意程
序效率。
*/

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

int findMaxLenDP( const string& query , const string& text )
{
	int Qlen = query.length();
	int Tlen = text.length();
	int** F = new int*[Qlen];//二維數組,存儲所有公共子串長度
	for( int i=0 ; i<Qlen ; i++ )
		F[i] = new int[Tlen];
	for( int i=0 ; i<Qlen ; i++ )
	{
		for( int j=0 ; j<Tlen ; j++ )
			F[i][j]=0;
	}

	//初始化第一行和第一列
	for( int i=0 ; i<Qlen ; i++ )
	{
		if( query[i] == text[0] )
			F[i][0] = 1;
	}

	for( int j=0 ; j<Tlen ; j++ )
	{
		if( text[j] == query[0] )
			F[0][j] = 1;
	}

	int maxSublen = 0;//存儲最大公共子串長度
	for( int i=1 ; i<Qlen ; i++ )
	{
		for( int j=1 ; j<Tlen ; j++ )
		{
			//狀態轉移方程
			if( query[i] == text[j] )
			{
				F[i][j] = F[i-1][j-1]+1;
				maxSublen = F[i][j]>maxSublen ? F[i][j] : maxSublen;
			}
			else
				F[i][j] = 0;
		}
	}

	for( int i=0 ; i<Qlen ; i++ )
		delete[] F[i];
	delete[] F;
	return maxSublen;
}
int main()
{
	cout << findMaxLenDP( "acbac" , "acaccbabb" ) << endl;
	system("pause");
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章