最長公共子串行求解 遞迴與動態規劃方法

2022-09-08 17:06:11 字數 3505 閱讀 5749

在做oj題目的時候,經常會用到字串的處理。例如,比較二個字串相似度。這篇文章介紹一下求兩個字串的最長公共子串行。

乙個字串的子串行,是指從該字串中去掉任意多個字元後剩下的字元在不改變順序的情況下組成的新字串。

最長公共子串行,是指多個字串可具有的長度最大的公共的子串行。

(1)遞迴方法求最長公共子串行的長度

1)設有字串a[0...n],b[0...m],下面就是遞推公式。

當陣列a和b對應位置字元相同時,則直接求解下乙個位置;當不同時取兩種情況中的較大數值。

2)**如下:

#include#include

char a[30],b[30

];int

lena,lenb;

int lcs(int,int

);  ///兩個引數分別表示陣列a的下標和陣列b的下標

intmain()

int lcs(int i,int

j)

用遞迴的方法優點是程式設計簡單,容易理解。缺點是效率不高,有大量的重複執行遞迴呼叫,而且只能求出最大公共子串行的長度,求不出具體的最大公共子串行。

(2)動態規劃求最長公共子串行的長度

動態規劃採用二維陣列來標識中間計算結果,避免重複的計算來提高效率。

1)最長公共子串行的長度的動態規劃方程

設有字串a[0...n],b[0...m],下面就是遞推公式。字串a對應的是二維陣列num的行,字串b對應的是二維陣列num的列。

另外,採用二維陣列flag來記錄下標ij的走向。數字"1"表示,斜向下;數字"2"表示,水平向右;數字"3"表示,豎直向下。這樣便於以後的求解最長公共子串行。

(2)求解公共子串行**

#include#include

char a[500],b[500

];char num[501][501]; ///

記錄中間結果的陣列

char flag[501][501]; ///

標記陣列,用於標識下標的走向,構造出公共子串行

void lcs(); ///

動態規劃求解

void getlcs(); ///

採用倒推方式求最長公共子串行

intmain()

void

lcs()

else

if(num[i][j-1]>num[i-1

][j])

else}}

}void

getlcs()

else

if(flag[i][j]==2) ///

如果是斜向右標記

j--;

else

if(flag[i][j]==3) ///

如果是斜向下標記

i--;

}for(i=k-1;i>=0;i--)

printf("%c

",res[i]);

}

(3)圖示

在做oj題目的時候,經常會用到字串的處理。例如,比較二個字串相似度。這篇文章介紹一下求兩個字串的最長公共子串行。

乙個字串的子串行,是指從該字串中去掉任意多個字元後剩下的字元在不改變順序的情況下組成的新字串。

最長公共子串行,是指多個字串可具有的長度最大的公共的子串行。

(1)遞迴方法求最長公共子串行的長度

1)設有字串a[0...n],b[0...m],下面就是遞推公式。

當陣列a和b對應位置字元相同時,則直接求解下乙個位置;當不同時取兩種情況中的較大數值。

2)**如下:

#include#include

char a[30],b[30

];int

lena,lenb;

int lcs(int,int

);  ///兩個引數分別表示陣列a的下標和陣列b的下標

intmain()

int lcs(int i,int

j)

用遞迴的方法優點是程式設計簡單,容易理解。缺點是效率不高,有大量的重複執行遞迴呼叫,而且只能求出最大公共子串行的長度,求不出具體的最大公共子串行。

(2)動態規劃求最長公共子串行的長度

動態規劃採用二維陣列來標識中間計算結果,避免重複的計算來提高效率。

1)最長公共子串行的長度的動態規劃方程

設有字串a[0...n],b[0...m],下面就是遞推公式。字串a對應的是二維陣列num的行,字串b對應的是二維陣列num的列。

另外,採用二維陣列flag來記錄下標ij的走向。數字"1"表示,斜向下;數字"2"表示,水平向右;數字"3"表示,豎直向下。這樣便於以後的求解最長公共子串行。

(2)求解公共子串行**

#include#include

char a[500],b[500

];char num[501][501]; ///

記錄中間結果的陣列

char flag[501][501]; ///

標記陣列,用於標識下標的走向,構造出公共子串行

void lcs(); ///

動態規劃求解

void getlcs(); ///

採用倒推方式求最長公共子串行

intmain()

void

lcs()

else

if(num[i][j-1]>num[i-1

][j])

else}}

}void

getlcs()

else

if(flag[i][j]==2) ///

如果是斜向右標記

j--;

else

if(flag[i][j]==3) ///

如果是斜向下標記

i--;

}for(i=k-1;i>=0;i--)

printf("%c

",res[i]);

}

(3)圖示

最長公共子串行求解 遞迴與動態規劃方法

在做oj題目的時候,經常會用到字串的處理。例如,比較二個字串相似度。這篇文章介紹一下求兩個字串的最長公共子串行。乙個字串的子串行,是指從該字串中去掉任意多個字元後剩下的字元在不改變順序的情況下組成的新字串。最長公共子串行,是指多個字串可具有的長度最大的公共的子串行。1 遞迴方法求最長公共子串行的長度...

最長公共子串行求解 遞迴與動態規劃方法

最長公共子串行求解 遞迴與動態規劃方法 在做oj題目的時候,經常會用到字串的處理。例如,比較二個字串相似度。這篇文章介紹一下求兩個字串的最長公共子串行。乙個字串的子串行,是指從該字串中去掉任意多個字元後剩下的字元在不改變順序的情況下組成的新字串。最長公共子串行,是指多個字串可具有的長度最大的公共的子...

最長公共子串行問題 最長公共子串問題 動態規劃

longest common subsequence problem 序列x和y,找到z為x和y的最大公共子串行 蠻力列舉 從x的長度為1序列開始列舉,在y中查詢是否有該序列 列舉觀察,長度為x 1的子串行是長度為x的子串行的一部分 存在最優子結構和重疊子問題,適合動態規劃 1 問題結構分析 c i...