zoukankan      html  css  js  c++  java
  • [leetcode] Longest Palindromic Substring

    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.

    https://oj.leetcode.com/problems/longest-palindromic-substring/

    思路1(naive approach):依次检查所有的子串(n^2),判断是否是palindrome(n),复杂度 O(n^3)。

    思路2(dp):dp[i][j] 代表从i到j的子串是否是palindrome。自下而上自左而右计算dp数组。时空复杂度都是 O(n^2)。

        dp[i][j]=1  if:

    1.     i=j;
    2.     s.charAt(i)==s.charAt(j)    &&    j-i<2
    3.     s.charAt(i)==s.charAt(j)    &&    dp[i+1][j-1]==1

    思路3:遍历字符串的每个字符,从这个字符出发(或者这个字符和下一个字符出发)向两侧辐射找出最长的子串。时间复杂度 O(n^2),空间复杂度O(1)。

    思路4:Manacher's algorithm。时空复杂度O(n)。

    http://www.felix021.com/blog/read.php?2040

    DP代码:

    public class Solution {
        public String longestPalindrome(String s) {
            if (s == null || s.length() == 0)
                return null;
            int start = 0;
            int end = 0;
            int len = 0;
            boolean[][] dp = new boolean[s.length()][s.length()];
            for (int i = s.length() - 1; i >= 0; i--) {
                for (int j = i; j < s.length(); j++) {
                    if (i == j || (s.charAt(i) == s.charAt(j) && j - i < 2)
                            || (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1])) {
                        dp[i][j] = true;
                        if (j - i + 1 > len) {
                            len = j - i;
                            start = i;
                            end = j + 1;
                        }
                    }
    
                }
            }
    
            return s.substring(start, end);
        }
    
        public static void main(String[] args) {
            System.out.println(new Solution().longestPalindrome("ababadccd"));
            System.out.println(new Solution().longestPalindrome("a"));
            System.out.println(new Solution().longestPalindrome(""));
    
        }
    
    }

    第二遍记录:注意dp的状态及转移函数。

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

    补思路3代码:

      注意向外扩展有两种情况。

      注意每次匹配向外匹配时长度增加2。

    public class Solution {
        public String longestPalindrome(String s) {
            if (s == null || s.length() <= 1)
                return s;
            int n = s.length();
            int maxLen = 0;
            String res = "";
    
            int tmpLen = 0;
            for (int i = 0; i < n - 1; i++) {
                tmpLen = getPalin(s, i);
                if (tmpLen > maxLen) {
                    maxLen = tmpLen;
                    res = s.substring(i - (tmpLen - 1) / 2, i - (tmpLen - 1) / 2 + tmpLen);
                }
                tmpLen = getPalin(s, i, i + 1);
                if (tmpLen > maxLen) {
                    maxLen = tmpLen;
                    res = s.substring(i - (tmpLen / 2 - 1), i - (tmpLen / 2 - 1) + tmpLen);
                }
    
            }
            return res;
    
        }
    
        private int getPalin(String s, int idx) {
            int len = 1;
            int i = idx - 1, j = idx + 1;
            while (i >= 0 && j < s.length()) {
                if (s.charAt(i) == s.charAt(j)) {
                    len += 2;
                    i--;
                    j++;
                } else
                    break;
            }
            return len;
    
        }
    
        private int getPalin(String s, int idx, int idy) {
            int len = 0;
            int i = idx, j = idy;
            while (i >= 0 && j < s.length()) {
                if (s.charAt(i) == s.charAt(j)) {
                    len += 2;
                    i--;
                    j++;
                } else
                    break;
            }
            return len;
    
        }
    
        public static void main(String[] args) {
            System.out.println(new Solution().longestPalindrome("abccba"));
        }
    
    }

    思路4代码:

      注意开头结尾的符号不要设成一样

    public class Solution {
    
        public String longestPalindrome(String s) {
            if (s == null || s.length() == 0)
                return "";
            int n = s.length();
            // preprocess the string
            StringBuilder sb = new StringBuilder();
            sb.append("$#");
            for (int i = 0; i < n; i++) {
                sb.append(s.charAt(i));
                sb.append('#');
            }
            sb.append('*');
            s = sb.toString();
            n = s.length();
            // System.out.println(s);
            int mx = 0, id = 0;
            int[] p = new int[n];
            int res = 0;
            int resIdx = -1;
            for (int i = 1; i < n - 1; i++) {
                p[i] = mx > i ? Math.min(p[2 * id - i], mx - i) : 1;
                while (s.charAt(i + p[i]) == s.charAt(i - p[i]))
                    p[i]++;
                // update mx and id
                if (i + p[i] > mx) {
                    mx = i + p[i];
                    id = i;
                }
                // record the max of p[i];
                if (p[i] > res) {
                    res = p[i];
                    resIdx = i;
                }
            }
            // construct the result string
            String resStr = s.substring(resIdx - (res - 1), resIdx + (res - 1) + 1);
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < resStr.length(); i++)
                if (resStr.charAt(i) != '#')
                    sb2.append(resStr.charAt(i));
            resStr = sb2.toString();
            return resStr;
        }
    
        public static void main(String[] args) {
            System.out.println(new Solution().longestPalindrome("12212321"));
        }
    
    }

    参考:

    http://www.programcreek.com/2013/12/leetcode-solution-of-longest-palindromic-substring-java/

    http://www.cnblogs.com/TenosDoIt/p/3675788.html

    http://blog.csdn.net/worldwindjp/article/details/22066307

  • 相关阅读:
    Codeforces 1037D【BFS】
    hdu 4725 The Shortest Path in Nya Graph 【拆点】+【最短路】
    LightOJ 1074
    POJ1062昂贵的聘礼(经典) 枚举区间 +【Dijkstra】
    POJ 3159 Candies 【差分约束+Dijkstra】
    POJ 3126 Prime Path【BFS】
    ZOJ 1940 Dungeon Master【三维BFS】
    POJ 3279 Fliptile (二进制枚举)
    HDU 2612 find a way 【双BFS】
    POJ 3414 Pot (输出路径)【BFS】
  • 原文地址:https://www.cnblogs.com/jdflyfly/p/3810674.html
Copyright © 2011-2022 走看看