[LeetCode] Longest Palindrome Substring 詳細分析,leetcodepalindrome

來源:互聯網
上載者:User

[LeetCode] Longest Palindrome Substring 詳細分析,leetcodepalindrome

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

面DP題的考官都是神經病。。(吐槽)

貌似挺容易出迴文的題,那麼今天仔細分析下DP的做法!!以解我被DP問題虐成渣渣的心碎感覺。如有錯誤請指出~


首先,拿了這個題,至少也可以給出一個O(n^3)的演算法,2層for迴圈加每次檢查一遍substring是不是迴文。我給出了一個必定逾時的代碼以供參考。

public String longestPalindrome(String s) {        if(s==null) return null;        // String[][] dp= new String[1000][1000];        // Arrays.fill(dp,1);        int max=1;        String result=s.substring(0,1);        for(int i=0;i<s.length()-1;i++){            for(int j=i+1;j<s.length();j++){                String temp=s.substring(i,j+1);                if(ifPalin(temp)){                    if(max<temp.length()){                        max=temp.length();                        result=temp;                    }                    if(max==s.length())                      return result;                }            }        }                return result;            }        public boolean ifPalin(String s){        if(s==null) return true;        int start=0;        int end=s.length()-1;                while(start<end){            if(s.charAt(start++)!=s.charAt(end--)){                return false;            }        }                return true;    }


這顯然不夠!如何最佳化?你會想到這種噁心題,dp那是必然的。那麼要分析迴文,必定要考慮到所有的情況。

↑上面Naive的方法逾時原因是因為:每次迴圈,都得看一遍當前子串是不是迴文,那麼如何解決這種重複性的工作呢?

通過對迴文性質的分析,我們可以看出來: 如果中間的某一段子串sub是迴文,如果sub兩側的字元是一樣的,那麼作為一個整體也是迴文。例如:

abcdcba      : d是迴文,cdc那麼就是迴文。 如果你再想一下,cdc是迴文,兩側b是一樣的,bcdcb也是迴文。咦,那麼abcdcba就是迴文了唄。

通過上個例子我們直接知道了答案。這是特例,那麼對於一般情況如何是好呢?所以第一個思路就是根據順向的思維推匯出來的:

我們申明一個dp[][]來儲存狀態。 對於dp[i][j]來說, 其意義就是 s.substring(i,j+1)是不是迴文。

(1)既然我們不知道哪裡為中心,向外拓展就能得到答案。那麼就以每個字元為中心,向外拓展,儲存一個最大的量,問題就解決了!

我們得初始化下dp, 單個字元是,所以dp[i][i]=true.

可是還有種情況, abcddcba,中間是兩個,不是一個,這也能構成迴文,這怎麼辦!

其實也好辦,我們就看看s.charAt(i)==s.charAt(i+1),如果是,就是迴文,我們就set  dp[i][i+1]=true

有了基礎的case,我們1層for迴圈移動中心點,用兩個指標start,end,分別拓展這兩種情況,來分析迴文,即可找出最大值。代碼如下:

 public String longestPalindrome(String s) {          if(s==null) return null;        boolean[][] dp= new boolean[s.length()][s.length()];        //define dp[i][j] is if s.substring(i,j+1) is palindrome:        int max=1;        String result=s.substring(0,1);        for(int i=0;i<s.length();i++){            dp[i][i]=true;        }        for(int i=0;i<s.length()-1;i++){            if(s.charAt(i)==s.charAt(i+1)){                dp[i][i+1]=true;                result=s.substring(i,i+2);                max=2;            }        }        for(int i=1;i<s.length()-1;i++){             int start=i-1,end=i+1;  //aba的情況             while(start>=0 && end<=s.length()-1){                if(dp[i][i] && s.charAt(start)==s.charAt(end)){                    dp[start][end]=true;                    if(max<end-start+1){                        max=end-start+1;                        result=s.substring(start,end+1);                    }                } else {                break;                }                start--;end++;             }             start=i-1;end=i+2;  //abba的情況             while(start>=0 && end<=s.length()-1){                if(dp[i][i+1] && s.charAt(start)==s.charAt(end)){                    dp[start][end]=true;                    if(max<end-start+1){                        max=end-start+1;                        result=s.substring(start,end+1);                    }                } else{                break;                }                start--;end++;             }        }                return result;            }

上面的代碼囉嗦了點,應該能簡化,我比較懶。。如果理解意思了就好辦! 

(2)上面的解法其實不太算dp,我們來考慮下真正的dp解法,但這個有時候很難想出來。。多琢磨吧。。

至少,如果你看到了這,耐心點再看一些,一定會理解dp解這個題的過程:

dp的思路是用以前做出來的結果作為基礎,然後推匯出新的結果。(2)的思路是:利用迴文的性質,如果判斷dp[i][j]是不是迴文,那麼要具備什嗎?

答案是:

1. s.charAt(i)==s.charAt(j)

2. dp[i+1][j-1] 是否為真

(這個代表當前的s.substring(i,j+1)往裡面縮一個的substring是否是迴文,有點繞。。舉例: abccbfee, 如果i=0,j=5,也就是abccbf,dp[i][j]就是說abccbf是不是迴文,根據之前的結果,如果s.charAt(i)==s.charAt(j),並且,bccb也是迴文,那麼dp[i][j]就為真. 這個例子中 a!=f, 雖然dp[i+1][j-1] (bccb)是迴文,那也不能算真)


所以這樣dp的精華就體現出來了:通過之前的結果,推導現在!

還有個關鍵點,就是dp的寫法。下午我把dp數組列印了出來,橫座標i從後往前,j是從i 到最後。1代表true,是迴文,0反之。

dp裡面挺多是從後面來的,當然我們不能記結果,而是要明白為什麼這麼做。

   

迴文的中心多數應該是在中心位置,所以,從後往前走,我們可以利用到之前的結果。 (從前往後走也是一樣的,只不過迴圈的參數要相應的變一下)

然而是上面的條件還不夠!如果說dp[i+1][j-1]為假,

但當i和j位置的字元是一致的,並且距離小於等於2的時候,那都是迴文,原因是只有3種情況: a (i=j)  aa (i=0,j=1) a*a(i=0,j=2)  *表示任一字元. 所以這樣我們可以當做迴文。

接著i不動,j接著走,超出了2的距離,也有可能會遇到和i一樣的字元,這時候是不是迴文?那就得看dp[i+1][j-1]是不是迴文,如果是,記錄,判斷是否超過當前最大長度。如果超過就替換最長字串。

看第二張圖,那三個1,其實就是例子中 abccbadd的推導過程, 當i=2的迴圈,j=2,是迴文,記錄。 i=2, j=3,“cc” 是迴文,繼續。 "ccb"不是迴文,

以上就是全部的分析,建議看文章的童鞋自己推導一遍過程。只有理解了為什麼這麼做,才能真正理解dp,從而寫出出精鍊乾淨的dp代碼

:下面代碼是從大神那看到的,拿過來的。

    public String longestPalindrome(String s) {          if(s==null || s.length()==1) return s;        boolean[][] dp= new boolean[s.length()][s.length()];        //define dp[i][j] is if s.substring(i,j+1) is palindrome:        int max=0;        String result=s.substring(0,1);        for(int i=s.length()-1;i>=0;i--){            for(int j=i;j<s.length();j++){                if(s.charAt(i)==s.charAt(j) && ((j-i<=2) || dp[i+1][j-1])){                    dp[i][j]=true;                    if(max<j-i+1){                        max=j-i+1;                        result=s.substring(i,j+1);                    }                }            }        }        return result;    }




ACM問題 這個題的輸入問題怎解決? http://acmswjtueducn/JudgeOnline/showproblem?problem_id=139

先把所有輸入都讀完,再去做進一步處理。

讀取代碼:
char *pBuf;
memset(buf, 0, sizeof(buf); // buf是你前面定義的數組
pBuf = buf;
while(gets(pBuf)) pBuf += strlen(pBuf);

這樣,所有字元都被讀進了buf,並且所有分行符號都被去除了。接下來你只要實現演算法部分就可以了。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.