前幾天做筆試題,遇到最長遞增子串行的問題,不知怎麼解,看網上有一種先將該序列排序,以轉化為求新序列與原有序列的最長公共子串。然而,最長公共子串行也!不!會!
這兩個演算法在大學時都應該是接觸過的,到此時居然已經忘的一乾二淨,才知道自己究竟差了多少功夫。於是先學一下最長公共子串行的解法,在這裡記下來,待下次再不會做時也好有個查閱的好地方。最長遞增子串行的解法改天再學。
設有字串a,b。
記a(0,i)為a從0位到i位的子串。
使用二維陣列c來記錄最長公共子串行長度,c[i][j]表示a(0,i)與b(0,j)的最長公共子串行長度。設c[-1][j] = c[i][-1] = 0,不論 i,j 取何值。
動態規劃的思路如下:
1)若a[i] == b[j],則c[i][j] = c[i-1][j-1] + 1
2)若a[i] != b[j],則c[i][j] = max
在其後構造最長公共子串行時,則逆向使用求最長公共子串行長度時的資料。首先初始化空的字串。
從表c右下角開始迴圈,記c[i][j],每次在下列三個表項中查詢最大值
a) c[i-1][j]
b) c[i][j-1]
c) c[i-1][j-1]
若a)最大,則令 i = i - 1
若b)最大,則令 j = j - 1
若c)最大,則在字串前插入a[i]的字元,而後令 i = i - 1,j = j - 1
其中可能出現 a),b) 兩數值相等,則說明有兩種構造最長公共子串行的方式,這兩種子串行可能相同,也可能不同。
為了簡化這個過程,也可以構造二維陣列d,來儲存構造最長公共子串行時,i,j 的調整方向。
二維陣列c的示意圖如下,來自演算法導論第三版。
寫練習**如下,未仔細推敲,大致應該或許沒有錯…
public
class
lcs
public
intcallength(string a, string b)
else
else
if(lengthtab[i-1][j] < lengthtab[i][j-1])
else}}
}// system.out.println("lengthtab:");
// printtab(lengthtab);
// system.out.println("directtab:");
// printtab(directtab);
return lengthtab[lena-1][lenb-1];
}public string getlcs(string a, string b)
//檢驗directtab行數和列數是否與字串長度匹配
if(directtab.length != a.length() + 1)
return
""; if(directtab.length <= 0 || directtab[0].length != b.length() + 1)
return
""; int lena = directtab.length - 1;
int lenb = directtab[0].length - 1;
//在表中查詢使匹配長度最大的路線(其中一條)
while(lena > 0 && lenb > 0)
//若此最大匹配子串的構造中,不包含a.charat(lena-1),尋找下乙個包含在子串中的字元
else
if(directtab[lena][lenb] == this.top)
else
if(directtab[lena][lenb] == this.left)
else
}return sb.tostring();
}public
void
printtab(int tab)
system.out.println();}}
private
int lengthtab = null;
private
int directtab = null;
//表示這乙個單元的最大匹配長度是從上一行同一列獲得
public
static
final
int top = -1;
//表示這乙個單元的最大匹配長度是從前一列同一行獲得
public
static
final
int left = 0;
//表示這乙個單元的最大匹配長度是左上角單元數值加1獲得
public
static
final
int top_and_left = 1;
//表示這乙個單元的最大匹配長度同其左側及上方的單元都一樣,
//top_or_left原為找到所有最長公共子串行而設,在這個例子中沒有實際使用,也未經測試是否有效,
//為避免有不同路徑的相同匹配子串行,可使用treeset等集合返回查詢結果,
//但需要注意轉殖方法,以及string類的comparable介面實現情況。
public
static
final
int top_or_left = 2;
}
動態規劃經典 最長公共子串行
最長公共子串行 時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 咱們就不拐彎抹角了,如題,需要你做的就是寫乙個程式,得出最長公共子串行。tip 最長公共子串行也稱作最長公共子串 不要求連續 英文縮寫為lcs longest common subsequence 其定義是,乙個...
動態規劃經典示例 最長公共子串和最長公共子串行
動態規劃經典示例 最長公共子串和最長公共子串行 舉例 str1 ghj8675fds str2 j86fdhl 最長公共子串是 j86 最長公共子串行是 j86fd 最長公共子串 dp i j 表示子串str1 0 i 和子串str 0 j 的最長公共子串 當str1 i str2 j 時,dp i...
最長公共子串 最長公共子串 動態規劃
有兩個字串 可能包含空格 請找出其中最長的公共連續子串,輸出其長度。長度在1000以內 例如 輸入 abcde bcd 輸出 3 1 把兩個字串分別以行和列組成乙個二維矩陣。2 比較二維矩陣中每個點對應行列字元中否相等,相等的話值設定為1,否則設定為0。3 通過查詢出值為1的最長對角線就能找到最長公...