【區間 dp】B010_LC_最長迴文子串(暴力 / dp / 中心擴展(代辦))

一、Problem

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

輸入:"aacdefcaa"
預期:"aa"

二、Solution

方法一:暴力

  • 不用先取子串,可以利用 s 的字符串數組根據索引進行全局比較
  • 取子串的話會超時的。
class Solution {
    char[] cs;
    public String longestPalindrome(String s) {
        if (s.length() == 1)
            return s;
        String res = "";
        cs = s.toCharArray();
        int max = 0;
        for (int i = 0; i < s.length(); i++) 
        for (int j = i; j < s.length(); j++) {
            if (is(i, j) && j-i+1 > max) {
                res = s.substring(i, j+1);
                max = j-i+1;
            }
        }
        return res;
    }
    boolean is(int l, int r) {
        while (l < r) {
            if (cs[l] != cs[r])
                return false;
            l++; r--;
        }
        return true;
    }
}

複雜度分析

  • 時間複雜度:O(n3)O(n^3)
  • 空間複雜度:O(1)O(1)

方法二:轉化爲 LMS 問題

從迴文串的性質出發,將問題轉化爲求解最長公共子串問題:

  • 定義狀態
    • dp[i][j]dp[i][j] 表示以 s1[i]s1[i] 開始和以 s[j]s[j] 結束的迴文子串的長度。
  • 思考初始化:
    • dp[i][i]=1dp[i][i] = 1 單個字符 LMS 長度爲 1
  • 思考狀態轉移方程
    • 如果 s1[i]=s[j]s1[i] = s[j],可推出 dp[i][j]=dp[i1][j1]+1dp[i][j] = dp[i-1][j-1] + 1
    • 否則,dp[i][j]=0dp[i][j] = 0
  • 思考輸出max(dp[0...n[0...n])max(dp[0...n[0...n])

還是 99 / 103 WA 了?這確實打臉…

"aacdefcaa"
輸出:"aac"
預期:"aa"
class Solution {
    public String longestPalindrome(String s) {
		char s1[] = s.toCharArray(), s2[] = new StringBuilder(s).reverse().toString().toCharArray();
		int max = 0, e = 0, n = s1.length, dp[][] = new int[n+1][n+1];
        for (int i = 1; i <= n; i++)
            dp[i][i] = 1;

		for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (s1[i-1] == s2[j-1])	{
                dp[i][j] = dp[i-1][j-1] + 1;
                if (dp[i][j] > max) {
                    max = dp[i][j];
                    e = i;
                }
            } else dp[i][j] = 0;
		}
		return s.substring(e-max, e);
    }
}

方法三:dp

  • 定義狀態
    • dp[l][r]dp[l][r] 的真值表示子串 s[l:r]s[l:r] 是否爲迴文子串
  • 思考初始化:
    • dp[i][i]=truedp[i][i] = true
  • 思考狀態轉移方程
    • 如果 s[l]=s[r]s[l] = s[r],此時會有兩種情況出現:
      • 如果 [l,r][l, r] 中間沒有字符,那麼 dp[l][r]=truedp[l][r] = true
      • 如果 [l,r][l, r] 中間存在字符,那麼 dp[l][r]=dp[l+1][r1]dp[l][r] = dp[l+1][r-1]
class Solution {
    public String longestPalindrome(String S) {
		char[] s = S.toCharArray();
		int max = 0, s = 0, n = s.length;
        boolean[][] dp = new boolean[n][n];
        
		for (int r = 0; r < n; r++)
		for (int l = 0; l <= r; l++) {
            if (s[l] == s[r] && (r - l < 2 || dp[l+1][r-1])) {
                dp[l][r] = true;
                if (r - l + 1 > max){
                    max = r-l+1;
                    s = l;
                }
            }
		}
		return S.substring(s, s+max);
    }
}

複雜度分析

  • 時間複雜度:O(n2)O(n^2)
  • 空間複雜度:O(n2)O(n^2)

還有啥中心擴展,代辦把

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章