最長公共子序列問題,就是找出兩個字符串中,存在的最長的
子序列
java
什麼是子序列呢?
子序列不一樣於公共子串,子串是每一個字符連續的,子序列不必定要連續,見下例 [example]
app
[example]: 好比 mStringA = "abc11google11111111", mStringB = "1111111141615" 這兩個字符串
那麼,mStringA 和 mStringB 的最長公共子序列就是 1111111111
post
咱們對於問題進行白話講解,假如如今有兩個字符串,而且有兩個指針,這每一個指針,各自指向這兩個字符串,咱們把這兩個指針設置爲 i 和 j,即,i 指向 mStringA 的某個字符,j 指向 mStringB 的某個字符,那麼,此時的狀態方程爲 f(i, j)
,表示 i 指向 mStringA 的某個字符和 j 指向 mStringB 的某個字符的狀況測試
- 當兩個指針指向的字符相等時,那麼表明這是一個成功的狀態,此時,狀態記爲
f(i + 1, j + 1) + 1
,表示 i 和 j 兩個指針能夠同時向右方移動- 當兩個指針指向的字符不相等的試試,那麼表明這是一個待完成的狀態,此時,狀態記爲
f(i + 1, j)
和f(i, j + 1)
package com.company; import org.junit.Test; public class LongestCommonSequence { // 用來存儲匹配過程當中存取的記錄 public StringBuilder sb = new StringBuilder(); /* * 得到最長公共子序列的方法 * 傳入兩個參數,即爲須要處理的字符串 * 核心實現方法在 longestCommonSequence(...) */ public String getLongestCommonSequence(String mStringA, String mStringB) { // 1. 拿到最長公共子序列的長度 int strLength = longestCommonSequence(0, mStringA, 0, mStringB); // 2. 將 StringBuilder 轉爲 String 類 String mString = new String(sb); // 3. 對記錄進行裁剪,最後的 strLength 個字符,是最終的結果 return mString.substring( strLength - longestCommonSequence(0, mStringA, 0, mStringB), strLength); } // 最長公共子序列的實現方法 public int longestCommonSequence(int i, String mStringA, int j, String mStringB) { // 1. 邊界條件判斷,當指針到頭的時候,返回 0 if (i == mStringA.length() || j == mStringB.length()) { return 0; } // 2. 當兩個指針指向的字符相等的時候,這是狀態方程爲:f(i + 1, j + 1) + 1 if (mStringA.charAt(i) == mStringB.charAt(j)) { sb.append(mStringA.charAt(i)); return longestCommonSequence(i + 1, mStringA, j + 1, mStringB) + 1; } else { // 3. 當兩個指針指向的字符不相等的時候,這是狀態方程爲:f(i + 1, j) 或者 f(i, j + 1) return Math.max(longestCommonSequence(i + 1, mStringA, j, mStringB), longestCommonSequence(i, mStringA, j + 1, mStringB)); } } // 測試方法 @Test public void test() { // 1111111111 System.out.println( getLongestCommonSequence("abc11google11111111", "1111111141615") ); } }