1. 程式人生 > >【探索-中級演算法】最長迴文子串

【探索-中級演算法】最長迴文子串

在這裡插入圖片描述

這一題可以參考:647. 迴文子串

本質上是一樣的,要判斷出所有的迴文字串,然後找到其中最長的那一個。


中心擴充套件法

中心擴充套件就是把給定的字串的每一個字母當做中心,向兩邊擴充套件,這樣來找最長的子迴文串。演算法複雜度為O(N^2)

public String longestPalindrome(String s) {
    if (s == null || s.length() < 1) return "";
    char[] strs = s.toCharArray();
    int len = strs.length;
    int
[] arr1 = new int[2]; int[] arr2 = new int[2]; //記錄起點與終點的位置 int start = 0, end = 0; for (int i = 0; i < len; i++) { //以 s(i) 為中心向兩邊擴散,得到最長的迴文子串 get(arr1, strs, i - 1, i + 1); //以 s(i) 與 s(i+1) 為中心向兩邊擴散,得到最長的迴文子串 get(arr2, strs, i, i + 1); int tmpStart,
tmpEnd; if (arr1[1] - arr1[0] > arr2[1] - arr2[0]) { tmpStart = arr1[0]; tmpEnd = arr1[1]; } else { tmpStart = arr2[0]; tmpEnd = arr2[1]; } if ((tmpEnd - tmpStart) > (end - start)) { start = tmpStart; end =
tmpEnd; } } return s.substring(start, end + 1); } public void get(int[] arr, char[] strs, int left, int right) { while (left >= 0 && right < strs.length && strs[left] == strs[right]) { --left; ++right; } ++left; --right; arr[0] = left; arr[1] = right; }

基於動態規劃

public String longestPalindrome(String s) {
    if (s == null || s.length() < 1) return "";
    int len = s.length();
    boolean dp[][] = new boolean[len][len];
    char[] strs = s.toCharArray();
    int start = 0, end = 0;
    // 判斷 dp[i][i+1] 是不是迴文
    for (int i = 0; i < len -1 ; i++) {
        if(strs[i] == strs[i + 1]) {
            dp[i][i + 1] = true;
            start = i;
            end = i + 1;
        }
		// dp[i][i] 即單個字母肯定是迴文
        dp[i][i] = true;
    }	
    //因為上面的迴圈無法設定最後一個字母,所以要在這裡設定
    dp[len - 1][len - 1] = true;

	// 按照 dp[i][j] = (dp[i + 1][j - 1] && (strs[i] == strs[j])) 
	// 的轉移方程來判斷 dp[i][j] 是不是迴文
	// 如果是的話還要與原有最長的比較是不是更長且記錄
    for (int i = len - 3; i >= 0; i--) {
        for (int j = i+2; j < len; j++) {
            dp[i][j] = (dp[i + 1][j - 1] && (strs[i] == strs[j]));
            if (dp[i][j]) {
                if (j - i > end - start) {
                    start = i;
                    end = j;
                }
            }
        }
    }
    return s.substring(start, end + 1);
}

dp[i][j] 表示 s 的子串 s[i,j] 是不是迴文。

需要注意的就是第二個迴圈遍歷的順序如下圖所示(折線表示計算的順序):
在這裡插入圖片描述