每天一道演算法題 最長公共子串行和最長公共子串

2021-08-08 04:49:31 字數 2856 閱讀 4333

最近刷題遇到很多與最長公共子串行或者子串有關的題,這裡回顧一下兩者的求解過程以及怎麼輸出列印。

最長公共子串(longest common substring)與最長公共子串行(longest common subsequence)的區別: 子串要求在原字串中是連續的,而子串行則只需保持相對順序,並不要求連續。

問題描述:

給定兩個序列:x[1…m]和y[1…n],求在兩個序列中同時出現的最長子序列的長度。

假設 x 和 y 的序列如下:

str1:

"abcbdab"

str2:

"bdcaba"

經典的解法是使用動態規劃來解:

假設z=z1,z2,⋯,zk>是x與y的lcs, 我們觀察到

如果xm=yn,則zk=xm=yn,有zk−1是xm−1與yn−1的lcs;

如果xm≠yn,則zk是xm與yn−1的lcs,或者是xm−1與yn的lcs。

因此,求解lcs的問題則變成遞迴求解的兩個子問題。但是,上述的遞迴求解的辦法中,重複的子問題多,效率低下。改進的辦法——用空間換時間,用陣列儲存中間狀態,方便後面的計算。這就是動態規劃(dp)的核心思想了。

狀態轉移方程式如下:

其實用矩陣圖來表示會更加清楚:

矩陣的最後的值就是最長公共子串行的長度,而在列印所有的最長公共子串行時,也是沿著最後乙個點向上溯源找,如果str1.charat(i) == str2.charat(j),記錄這個序列點,然後向斜對角線方向繼續尋找。而當table[i-1][j] > table[i][j-1](這裡的table指上面的二維陣列),向左邊方向繼續尋找序列點;當table[i-1][j] < table[i][j-1],向上方向尋找序列點。而當存在table[i-1][j]==table[i][j-1]時,說明存在不同的最長公共子串行,則進一步遞迴尋找。

public

class

longestcommonsubsequence

/**

* 功能:求兩個數中的較大者

*/private

intmax(int a, int b)

/**

* 功能:構造表,並返回x和y的lcs的長度

*/private

intlcs(int m, int n)

} return table[m][n];

} /**

* 功能:回溯,求出所有的最長公共子串行,並放入set中

*/private

void

traceback(int i, int j, string lcs_str)

else

} }

set.add(reverse(lcs_str));

} /**

* 功能:字串逆序

*/private string reverse(string str)

/**

* 功能:外部介面 —— 列印輸出

*/public

void

printlcs()

} /**

* 功能:main方法 —— 程式的入口

*/public

static

void

main(string args)

}

而最長公共子串則強調連續的條件,因此其狀態轉移方程式為:

最長公共子串在二維陣列中則表現為連續的對角線數值不為0。其中數值最大則為最長公共子串的長度。而在輸出列印所有最長公共子串時,可以遍歷尋找數值為最長公共子串的長度,之後沿著對角線遍歷尋找最長公共子串。

public

class

longestcommonsubstring

/**

* 功能:構造表,並返回x和y的lcs的長度

*/private

intlcs(int m, int n) else

if(x.charat(i-1)==y.charat(j-1))else}}

traceback(table, m, n, result);

return result;

} /**

* 功能:(用乙個比較笨的方法,遍歷array,找出result所在的位置,對角線遍歷最長公共字串)

*/private

void

traceback(int lcsarray,int i, int j,int result)

--i;

--j;

}

} public

void

printlcs(int lcsarray,int i,int j)

system.out.println(reverse(str));

}/**

* 功能:字串逆序

*/private string reverse(string str)

/**

* 功能:main方法 —— 程式的入口

*/public

static

void

main(string args)

}

每天一道演算法題

no.1 棧是特殊的線性表,它。a.對 b.錯答案 錯,它的插入和刪除都是在同一端進行的。no.2 n個葉子節點的滿二叉樹 除了葉子節點,每個節點都有兩個孩子 總共有多少個節點?a.2n 1 b.2n c.n 1 d.n答案 a 滿二叉樹我們講過了,度為0的節點比度為2的加點多乙個。滿二叉樹是特殊的...

每天一道演算法題

1.給定乙個只包括 的字串,判斷字串是否匹配。有效字串需滿足 左括號必須用相同型別的右括號閉合。左括號必須以正確的順序閉合。注意空字串可被認為是有效字串。思路 正確思路 不需要考慮輸入內容是否合法,這只是做題,不是工程 定義乙個字典,後括號為鍵,前半部分為值 定義乙個元素儲存棧頂,注意這個設定,取棧...

每天一道演算法題

1 js計算某個字串出現的次數 j ascript計算乙個字串最多重複的字元及出現次數.var str zhaochucichuzuiduodezifu var o for var i 0,length str.length i length i else console.log o 輸出的是完整的...