[dp]Leetcode 5. Longest Palindromic Substring

输入:一个字符串s
输出:最长的回文子串
规则:“abba"是一个回文
分析:输入是"babad”,输出"bab"。这个问题不能再按照之前分段的思路解决,或者说完全按照之前的思路。

之前的思路是:如果字符串只包含b,只包含ba,只包含bab…

因为要判断回文是要有以某个点为圆心的思想。最直观的感觉是从中间位置(n/2)开始判断。但思路没有进行下去。

如果已知"aba"是一个回文,那么"babab"也是一个回文。这是dp的核心逻辑。(怎么找到这个逻辑?)
d p [ i ] [ j ] = t r u e , i j dp[i][j]=true,如果字符串从i到j是一个回文 d p [ i ] [ j ] = f a l s e , i j dp[i][j]=false,如果字符串从i到j不是一个回文
如果 s [ i ] = s [ j ] d p [ i + 1 ] [ j 1 ] = t r u e s[i]=s[j]并且dp[i+1][j-1]=true ,那么 d p [ i ] [ j ] = t r u e dp[i][j]=true
基本情况是: d p [ i ] [ i ] = t r u e dp[i][i]=true ,单个元素是回文; d p [ i ] [ i + 1 ] = t r u e , s [ i ] = s [ i + 1 ] dp[i][i+1]=true,当s[i]=s[i+1] ,相邻元素相同。
这段代码编写也会是难点。

	public String longestPalindrome(String s) {
        if(s==null || s.length()==0) return s;
        int n = s.length();
    
        boolean[][] dp = new boolean[n][n];
        int maxlen = 1;
        int start = 0;
        for(int i=0;i<n;i++){
            dp[i][i] = true;
            if(i<n-1 && s.charAt(i)==s.charAt(i+1)){
                dp[i][i+1]=true;
                start = i;
                maxlen=2;
            }
        }
        for(int j=2;j<n;j++){
            for(int i=0;i<j;i++){
                if(dp[i+1][j-1] && s.charAt(i) == s.charAt(j)){
                    dp[i][j]=true;
                    if(j-i+1>maxlen){
                        maxlen = j-i+1;
                        start = i;
                    }
                }
            }
        }
        return s.substring(start,start+maxlen);
    }

分析2:仍然是一种以某个点为中心的思想,一个回文字符串中心的点可能是一个,也可能是两个。会有2n-1个中心点。
例如"babad"。
以b为中心,ba为中心
以a为中心,以ab为中心
以b(第2位)为中心,以ba为中心

直到结束

 public String longestPalindrome(String s) {
        if(s==null || s.length()==0) return s;
        int start = 0;
        int maxLen = 1;
        for(int i=0;i<s.length();i++){
            int len1 = expandAroundCenter(s,i,i);
            int len2 = expandAroundCenter(s,i,i+1);
            int len = Math.max(len1,len2);
            if(len>maxLen){
                start = i - (len-1)/2;
                maxLen = len;
            }
        }
        return s.substring(start,start+maxLen);
    }
    
    private int expandAroundCenter(String s ,int left,int right){
        while(left>=0 && right<s.length() && s.charAt(left)==s.charAt(right)){
            left--;
            right++;
        }
        return right-left -1;
    }

分析3:Manacher 算法

public String longestPalindrome(String s) {
        if(s==null || s.length()==0) return s;
        char splitChar = '#';
        String str = changeString(s,splitChar);
        int n = str.length();
        int[] dp = new int[n];
        int max = 1;
        int middel = 1;
        for(int i=1;i<n;i++){
            int step = 0;
            int l = i-1;
            int r = i+1;
            while(l>=0 && r<n && str.charAt(l)==str.charAt(r)){
                l--;
                r++;
                step++;
            }
            dp[i] = step;
            if(step>max){
                max = step;
                middel = i;
            }
        }
        int start = (middel - max)/2;        
        return s.substring(start,start+max);
    }
    
    private String changeString(String s,char splitChar){
        StringBuilder str = new StringBuilder();
        str.append(splitChar);
        for(int i=0;i<s.length();i++){
            str.append(s.charAt(i));
            str.append(splitChar);
        }
        return str.toString();
    }

参考文章:link
link

发布了148 篇原创文章 · 获赞 35 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/flying_all/article/details/103844324