LCS問題就是求兩個字符串最長公共子串的問題。解法就是用一個矩陣來記錄兩個字符串中所有位置的兩個字符之間的匹配情況,若是匹配則爲1,否則爲0。然後求出對角線最長的1序列,其對應的位置就是最長匹配子串的位置.
下面是字符串21232523311324和字符串312123223445的匹配矩陣,前者爲X方向的,後者爲Y方向的。不難找到,紅色部分是最長的匹配子串。通過查找位置我們得到最長的匹配子串爲:21232
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
0 1 0 0 0 0 0 0 0 1 1 0 0 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 0 1 1 0 0 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
但是在0和1的矩陣中找最長的1對角線序列又要花去一定的時間。通過改進矩陣的生成方式和設置標記變量,可以省去這部分時間。下面是新的矩陣生成方式:
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
0 1 0 0 0 0 0 0 0 2 1 0 0 0 0
1 0 2 0 1 0 1 0 0 0 0 0 1 0 0
0 2 0 0 0 0 0 0 0 1 1 0 0 0 0
1 0 3 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 4 0 0 0 2 1 0 0 1 0 0 0
1 0 1 0 5 0 1 0 0 0 0 0 2 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 2 0 0 0 2 1 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
當字符匹配的時候,我們並不是簡單的給相應元素賦上1,而是賦上其左上角元素的值加一。我們用兩個標記變量來標記矩陣中值最大的元素的位置,在矩陣生成的過程中來判斷當前生成的元素的值是不是最大的,據此來改變標記變量的值,那麼到矩陣完成的時候,最長匹配子串的位置和長度就已經出來了。
[Source:http://blog.sina.com.cn/s/blog_4cf5d24301000bs3.html]
-----------------------------------------------
【注】:
採用上述的第二種矩陣生成方式時,還可以把輔助空間開銷降低到O(min(len1, len2)),其中len1和len2分別是兩個字符串的長度。
具體方法如下:
令LEN=min(len1, len2),依上述第二種矩陣生成原理,從第一行(列)起,由上(左)往下(右)依次生成得到各行(列)的數值,由於每一行(列)的數據的生成只需要通過兩個母串的對比和藉助上一行(列)的結果得到,因此除了當前行(列)的上一行(列),之前的行(列)的數據均可以被拋棄,因此,該算法只需要用於保存上一行(列)的計算結果的長爲LEN的輔助數組空間和幾個額外記錄單元即可。(注:對當前行(列)計算結果的保存只需要對輔助數組做更新操作即可,這個就不用說啦,呵~)