[LeetCode] 4. Longest Palindrome Substring 分析+代码

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

Input: "babad"


Output: "bab"


Note: "aba" is also a valid answer.

Input: "cbbd"


Output: "bb"

native的方法 2层循环 验证每一个可能的子字符串是否是回文,再加一层验证回文的函数要一层循环,总的是 O(n3)复杂度

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;  
    }  

brutal force的算法把所有的可能的substring 都去做了验证是否事palindrome. 为了优化,我们首先分析如何能避免不必要的重复计算。 

通过对回文性质的分析,我们可以看出来: 如果中间的某一段子串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,分别拓展这两种情况,来分析回文,即可找出最大值。

第一种,用dp的方法,dp的思路是用以前做出来的结果作为基础,然后推导出新的结果,首先要分析特例: 

如果P[i,j]为真,当且仅当si-1,si-2...sj-1,sj这一个子串都为palindrome。例如:s[] = skrdjdre那么P[2][6] = true,因为s[2]=r=s[6],且djd为回文。

代码如下:

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;  
         
   }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值