一、問題描述
如果字串一的所有字元按其在字串中的順序出現在另外乙個字串二中,
則字串一稱之為字串二的子串。
注意,並不要求子串(字串一)的字元必須連續出現在字串二中。
請編寫乙個函式,輸入兩個字串,求它們的最長公共子串,並列印出最長公共子串。
例如:輸入兩個字串bdcaba和abcbdab,字串bcba和bdab都是是它們的最長公共子串行,則輸出它們的長度4,並列印任意乙個子串行。
二、最長公共子串行的結構
最長公共子串行的結構有如下表示:
設序列x=1, x2, …, xm>和y=1, y2, …, yn>的乙個最長公共子串行z=1, z2, …, zk>,則:
若xm=yn,則zk=xm=yn且zk-1是xm-1和yn-1的最長公共子串行;
若xm≠yn且zk≠xm ,則z是xm-1和y的最長公共子串行;
若xm≠yn且zk≠yn ,則z是x和yn-1的最長公共子串行。
其中xm-1=1, x2, …, xm-1>,yn-1=1, y2, …, yn-1>,zk-1=1, z2, …, zk-1>。
三、子問題的遞迴結構
由最長公共子串行問題的最優子結構性質可知,要找出x=1, x2, …, xm>和y=1, y2, …, yn>的最長公共子串行,可按以下方式遞迴地進行:當xm=yn時,找出xm-1和yn-1的最長公共子串行,然後在其尾部加上xm(=yn)即可得x和y的乙個最長公共子串行。當xm≠yn時,必須解兩個子問題,即找出xm-1和y的乙個最長公共子串行及x和yn-1的乙個最長公共子串行。這兩個公共子串行中較長者即為x和y的乙個最長公共子串行。
由此遞迴結構容易看到最長公共子串行問題具有子問題重疊性質。例如,在計算x和y的最長公共子串行時,可能要計算出x和yn-1及xm-1和y的最長公共子串行。而這兩個子問題都包含乙個公共子問題,即計算xm-1和yn-1的最長公共子串行。
與矩陣連乘積最優計算次序問題類似,我們來建立子問題的最優值的遞迴關係。用c[i,j]記錄序列xi和yj的最長公共子串行的長度。其中xi=1, x2, …, xi>,yj=1, y2, …, yj>。當i=0或j=0時,空序列是xi和yj的最長公共子串行,故c[i,j]=0。其他情況下,由定理可建立遞迴關係如下:
四、演算法實現
#include#include#includeusing namespace std;
enum direction;
void printlcs(int **lcs_direct,char *pstr1,char *pstr2,int row,int col)
cout<1)
} else if(lcs_direct[row][col]==left)
}}int lcs(char *pstr1,char *pstr2)
size_t strlen1 = strlen(pstr1);
size_t strlen2 = strlen(pstr2);
if(strlen1==0||strlen2==0)
//建立並初始化記錄最大長度的矩陣
int i,j;
int **lcs_length;
lcs_length = (int**)(new int[strlen1+1]);
for(i=0;ilcs_length[i+1][j])
else
} }
for(i=0;i
動態規劃解決最長公共串問題
LCS求最長公共子串
問題描述 給兩個子串行a和b,求長度最長的公共子串行,如1,5,2,6,8,7和2,3,5,6,9,8,4的最長公共子串行為5,6,8另乙個解為2,6,8求出這樣的子串行最長是多少?狀態轉移方程 對a1,a2 ai和b1,b2,bj 當a i b j 時,d i,j d i 1,j 1 1 否則d ...
最長公共子串行演算法(LCS)及最長公共子串求法
最長公共子串行演算法c 實現 string lcs string s1,string s2 int m s1.length 1 int n s2.length 1 動態二維陣列的定義方法 int lcs new int m for int i 0 i m i for int i 0 i m i 生成...
最長公共子串LCS
找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。其實這又是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公共子串是 ba 或 ab b a b c 0 0 0 a ...