想把演算法描述清楚真是件費時費力費腦筋的事情啊,下面的演算法描述部分源自以下連線:
感謝哥麼寫的文字描述的很清晰;
我用兩種方式實現「最長公共子串行」演算法:
1.動態規劃的順序實現;
2.動態規劃的遞迴實現;
最長公共子串行
最長公共子串行與最長公共子串的區別在於最長公共子串行不要求在原字串中是連續的,比如ade和abcde的最長公共子串行是ade。
我們用動態規劃的方法來思考這個問題如是求解。首先要找到狀態轉移方程:
符號約定,c1是s1的最右側字元,c2是s2的最右側字元,s1『是從s1中去除c1的部分,s2'是從s2中去除c2的部分。
lcs(s1,s2)等於下列3項的最大者:
(1)lcs(s1,s2』)
(2)lcs(s1』,s2)
(3)lcs(s1』,s2』)--如果c1不等於c2; lcs(s1',s2')+c1--如果c1等於c2;
邊界終止條件:如果s1和s2都是空串,則結果也是空串。
下面我們同樣要構建乙個矩陣來儲存動態規劃過程中子問題的解。這個矩陣中的每個數字代表了該行和該列之前的lcs的長度。與上面剛剛分析出的狀態轉移議程相對應,矩陣中每個格仔裡的數字應該這麼填,它等於以下3項的最大值:
(1)上面乙個格仔裡的數字
(2)左邊乙個格仔裡的數字
(3)左上角那個格仔裡的數字(如果 c1不等於c2); 左上角那個格仔裡的數字+1( 如果c1等於c2)
舉個例子:
g c t a
0 0 0 0 0
g 0 1 1 1 1
b 0 1 1 1 1
t 0 1 1 2 2
a 0 1 1 2 3
填寫最後乙個數字時,它應該是下面三個的最大者:
(1)上邊的數字2
(2)左邊的數字2
(3)左上角的數字2+1=3,因為此時c1==c2
所以最終結果是3。
在填寫過程中我們還是記錄下當前單元格的數字來自於哪個單元格,以方便最後我們回溯找出最長公共子串。有時候左上、左、上三者中有多個同時達到最大,那麼任取其中之一,但是在整個過程中你必須遵循固定的優先標準。在我的**中優先級別是左上》左》上。
下圖給出了回溯法找出lcs的過程:
1.以上動態規劃思想的順序實現,**如下:
#include #include執行結果:#define max 100
#define max(a,b) (a>b)?a:b#include
int ret[max][max]=};
int lcs(char stra,int lena,char strb,int
lenb)
}return
ret[lena][lenb];
}int
main()
xu@xu-thinkpad-x61:~/algorithm$ ./a.out
ret[1][1] = 1 same=1 ,tmp=0
ret[1][2] = 1 same=0 ,tmp=1
ret[1][3] = 1 same=1 ,tmp=1
ret[1][4] = 1 same=0 ,tmp=1
ret[2][1] = 1 same=0 ,tmp=1
ret[2][2] = 2 same=1 ,tmp=1
ret[2][3] = 2 same=0 ,tmp=2
ret[2][4] = 2 same=1 ,tmp=2
ret[3][1] = 1 same=0 ,tmp=1
ret[3][2] = 2 same=1 ,tmp=2
ret[3][3] = 2 same=0 ,tmp=2
ret[3][4] = 3 same=1 ,tmp=2
ret[4][1] = 1 same=0 ,tmp=1
ret[4][2] = 2 same=1 ,tmp=2
ret[4][3] = 2 same=0 ,tmp=2
ret[4][4] = 3 same=1 ,tmp=3
ret[5][1] = 1 same=0 ,tmp=1
ret[5][2] = 2 same=0 ,tmp=2
ret[5][3] = 2 same=0 ,tmp=2
ret[5][4] = 3 same=0 ,tmp=3
ret is:3,lena=5,lenb=4
2.下面是遞迴方式實現的**:
#include #include執行結果:#include
#define max 100
#define max(a,b) (a>b)?a:b
int lcs(char stra,int lena,char strb,int
lenb)
intmain()
xu@xu-thinkpad-x61:~/algorithm$ gcc lcs1.c遞迴執行很慢啊,機器太爛,字串長度到9就跑的沒完了!xu@xu-thinkpad-x61:~/algorithm$ ./a.out
result
is:3
xu@xu-thinkpad-x61:~/algorithm$
最長公共子串行 最長公共子串
1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...
最長公共子串行 最長公共子串
1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...
最長公共子串 最長公共子串行
子串要求連續 子串行不要求連續 之前的做法是dp求子序列 include include include using namespace std const int inf 0x3f3f3f3f const int mod 1000000007 string s1,s2 int dp 1010 10...