乙個給定序列的子串行是在該序列中刪去若干元素後得到的序列。確切的說,若給定序列x=,則另一串行z=,x的子串行是指存在乙個嚴格遞增下標序列使得對於所有j=1,2,…k有zj=xij 例如,序列z=是序列x=的子串行,相應的遞增下標序列為.
給定兩個序列x和y,當另一串行z既是x的子串行又是y的子串行時,稱z是序列x和y的公共子串行,公共子串行可以有多個,最長公共子串行是x和y序列的最長的乙個.
計算最長公共子串行的長度根據上面的式子來算就行了,但是兩個序列的最長公共子串行不止乙個,所以難點是如何得到它們,不難猜到,需要用回溯法來解決。具體做法是在計算長度的時候,用乙個陣列儲存當前點是從哪個狀態轉移過來的。
如果是xi == yj,那就是從c[i-1][j-1]轉移過來的,記為"↖"利用回溯法從右下角的節點的開始,根據節點儲存的狀態返回到上乙個狀態,如同根據方向走路一樣。。如果是「↖」的狀態表示是有乙個如果是c[i-1][j] > c[i][j-1],那就是從c[i-1][j]轉移過來的,記為"↑"
如果是c[i-1][j] < c[i][j-1],那就是從c[i][j-1]轉移過來的,記為"←"
如果是c[i-1][j] == c[i][j-1],那兩個狀態都可以轉移過來,記為"┘"
xi == yj
,將其追加到乙個字串lcs
後面,如此反覆,結束條件就是走到了邊界,這時需要判斷lcs
的長度是否是最長的長度,如果是最長的,那就找到了乙個儲存下來,這個回溯就走到了終點,返回即可。
public class test
public static int lcs(string a, string b) else if(c[i-1][j] > c[i][j-1]) else if(c[i-1][j] < c[i][j-1]) else
system.out.print(j == m ? c[i][j] + "\n":c[i][j] + " ");}}
for(int i = 0; i <= n; ++i)
}string lcs = "";
setlcsset = new hashset<>();
backtrace(d,a,lcs,n,m,c[n][m],lcsset);
for(string s: lcsset)
return c[n][m];
}public static void backtrace(char d, string a, string lcs, int i , int j, int maxsublen, setlcsset)
return;
}switch (d[i][j])}}
所有最長公共子串行
include include include include include include include include using namespace std setall lcs 注意這裡要用set去除重複的lcs 最長公共子串 lcs 二維陣列veca i j 記錄的是兩個字串xi和yj...
最長公共子串行 最長公共子串
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 當然我們現在一眼就可以看出來最長公...