1. 程式人生 > >LeetCode:最長回文子串【5】

LeetCode:最長回文子串【5】

msu 產生 嘗試 ++ 不必要 code 分享 規劃 color

LeetCode:最長回文子串【5】

題目描述

給定一個字符串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為1000。

示例 1:

輸入: "babad"
輸出: "bab"
註意: "aba"也是一個有效答案。

示例 2:

輸入: "cbbd"
輸出: "bb"

題目分析

  1.一個常見的錯誤!

    有些人會忍不住提出一個快速的解決方案,不幸的是,這個解決方案有缺陷(但是可以很容易地糾正):

反轉 SS,使之變成 S‘S′。找到 SS 和 S‘S′ 之間最長的公共子串,這也必然是最長的回文子串。

  這似乎是可行的,讓我們看看下面的一些例子。例如,S=“caba” , S=“abac”:

SS 以及 S‘S′ 之間的最長公共子串為“aba”,恰恰是答案。

  讓我們嘗試一下這個例子:S=“abacdfgdcaba” , S=“abacdgfdcaba”:SS 以及 S‘S′ 之間的最長公共子串為“abacd”,顯然,這不是回文。

  2.動態規劃的思路!

  為了改進暴力法,我們首先觀察如何避免在驗證回文時進行不必要的重復計算。考慮“ababa” 這個示例。如果我們已經知道 “bab” 是回文,那麽很明顯,“ababa” 一定是回文,因為它的左首字母和右尾字母是相同的

  我們給出P(i,j)的定義如下:

  技術分享圖片

  因此有,

  技術分享圖片

  這產生了一個直觀的動態規劃解法,我們首先初始化一字母和二字母的回文,然後找到所有三字母回文,並依此類推

Java題解

class Solution {
    public String longestPalindrome(String s) {
        if(s==null||s.length()==0)
            return s;
        String res ="";
        boolean [][] dp = new boolean[s.length()][s.length()];
        int max = 0;
        for(int j=0;j<s.length();j++)
        {
            for(int i=0;i<=j;i++)
            {
                if(i==j||((j==i+1)&&s.charAt(i)==s.charAt(j)))
                    dp[i][j]=true;
                else
                    dp[i][j]=(s.charAt(i)==s.charAt(j))&&(dp[i+1][j-1]);
                if(dp[i][j]&&j-i+1>max)
                {
                    max=j-i+1;
                    res = s.substring(i,j+1);
                }
            }
        }
        return res;
    }
}

  

LeetCode:最長回文子串【5】