1. 程式人生 > >動態規劃1.求最長迴文子串

動態規劃1.求最長迴文子串

求字串的子串大致有四中方法,暴力,DP,中心拓展,馬拉車演算法,這篇講DP怎麼做。

DP最重要的就是要能利用到前面的結果來推斷當前狀態,比暴力優化的地方就在此,暴力需要對每一個字串做一次O(n)的操作才能判斷出結果,也就是整個過程要O(n^3),但DP對每一個字串的判斷時間是O(1),總共是O(n^2)

假設s=adcdf,我們可以的推導過程就像下圖(i代表行,表示結尾,表示字串結尾,j代表列,表示字串開頭)

1 2 3 4 5
1 a
2 ad d
3 adc dc c
4 adcd dcd cd d
5 adcdf dcdf cdf df f

我們用dp[][]來表示所有可能子串是否迴文,比如dp[1][2]表示第ad,不迴文,所以dp[1][2]=false,根據上面表格可以總結一下
1.當i=j時,dp[j][i]=true
2.i-j=1時,比如dp[1][2]為ad,表示兩個相鄰的字元,此時我們只要判斷str[1]==str[2]就能得出dp[1][2]的結果
3.i-j>1時,我們來看dp[j]ij],首先還是要判斷開頭和結尾是否相等,也就是判斷
str[i]==str[j],假如此時str[i]=str[j],我們還要再看剩下的子串是否迴文,
我們可以直接從dp[j+1][i-1]來判斷剩下的子串,把結果直接拿來用

dp[j][i]=(str[i]==str[j]) ;i-j<=1
dp[j][i]=(str[i]==str[j])&&dp[j+1][i-1];i-j>1

class Solution {
    public String longestPalindrome(String s) {
        if(s.isEmpty()==true) return "";
        int Len=s.length();
        if(Len==1) return s;
        Boolean[][] dp=new Boolean[Len][Len];
        int len=0,max=0,start=0,end=0;      
        for(int i=0;i<Len;i++) {
            for(int j=0;j<=i;j++) {
                if(i-j>1) {
                    dp[j][i]=((s.charAt(i)==s.charAt(j))&&dp[j+1][i-1]);
                }else {
                    dp[j][i]=(s.charAt(i)==s.charAt(j));
                }
                len=i-j;
                if(dp[j][i]==true&&len>=max) { 
                    max=len;
                    start=j;
                    end=i;
                } 
            }
        }
        if(start==end) {
            String str="";
            return str+s.charAt(0);
        }           
        return s.substring(start, end+1);
    }
}

題目連結:點這裡