zoukankan      html  css  js  c++  java
  • LeetCode 5 -- Longest Palindromic Substring

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


    第一种方法比较直接,实现起来比较容易理解。基本思路是对于每个子串的中心(可以是一个字符,或者是两个字符的间隙,比如串abc,中心可以是a,b,c,或者是ab的间隙,bc的间隙)往两边同时进行扫描,直到不是回文串为止。假设字符串的长度为n,那么中心的个数为2*n-1(字符作为中心有n个,间隙有n-1个)。对于每个中心往两边扫描的复杂度为O(n),所以时间复杂度为O((2*n-1)*n)=O(n^2),空间复杂度为O(1),代码如下:

     1 package Leetcode;
     2 
     3 //提交时成功的,为什么结果却只是首字母?
     4 
     5 public class LongestPalindromeSubstring {
     6     public static String longestPalindrome(String s) {
     7         if (s == null || s.length() == 0)
     8             return "";
     9         int maxLen = 0;
    10         String res = "";
    11 
    12         for (int i = 0; i < 2*s.length() - 1; i++) {
    13              int left = i / 2;
    14             int right = i / 2;
    15             if (i % 2 == 1)
    16                 right++;
    17 
    18             String str = lengthOfPalindrome(s, left, right);
    19 
    20             if (str.length() > maxLen) {
    21                 res = str;
    22                 maxLen = str.length();
    23             }
    24         }
    25         return res;
    26     }
    27 
    28     public static String lengthOfPalindrome(String str, int left, int right) {
    29         while (left >= 0 && right < str.length()
    30                 && str.charAt(left) == str.charAt(right)) {
    31             left--;
    32             right++;
    33         }
    34         return str.substring(left + 1, right);
    35     }
    36     
    37     public static void main(String[] args){
    38         String str = "sabcbafds";
    39         String res = longestPalindrome(str);
    40         System.out.println(res);
    41     }
    42 
    43 }

    而第二种方法是用动态规划,思路比较复杂一些,但是实现代码会比较简短。基本思路是外层循环i从后往前扫,内层循环j从i当前字符扫到结尾处。过程中使用的历史信息是从i+1到n之间的任意子串是否是回文已经被记录下来,所以不用重新判断,只需要比较一下头尾字符即可。这种方法使用两层循环,时间复杂度是O(n^2)。而空间上因为需要记录任意子串是否为回文,需要O(n^2)的空间,代码如下:

     1 public String longestPalindrome(String s) {
     2   if(s == null || s.length()==0)
     3     return "";
     4   boolean[][] palin = new boolean[s.length()][s.length()];
     5   String res = "";
     6   int maxLen = 0;
     7   for(int i=s.length()-1;i>=0;i--)
     8   {
     9     for(int j=i;j<s.length();j++)
    10     {
    11       if(s.charAt(i)==s.charAt(j) && (j-i<=2 || palin[i+1][j-1]))
    12       {
    13         palin[i][j] = true;
    14         if(maxLen<j-i+1)
    15         {
    16           maxLen=j-i+1;
    17           res = s.substring(i,j+1);
    18         }
    19       }
    20     }
    21   }
    22   return res;
    23 }

    还有另外一种更简单的方法,复杂度O(n),但没怎么搞懂

    参考 http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

    // Manacher algorithm
     
    // Transform S into T
    // For example, S = "abba", T = "^#a#b#b#a#$"
    // ^ and $ signs are sentinels appended to each string
    // to avoid bound checking
    string preProcess(string s)
    {
      int n = s.length();
      if (n == 0) return "^$";
      string ret = "^";
      for (int i = 0; i < n; ++i)
        ret += "#" + s.substr(i, 1);
      ret += "#$";
      return ret;
    }
     
    string longestPalindromeManacher(string s)
    {
      string T = preProcess(s);
      int n = T.length();
      vector<int> p(n, 0);
      int C = 0, R = 0;
      for (int i = 1; i < n-1; ++i){
        int i_mirror = 2*C-i;
     
        p[i] = (i < R) ? min(R-i, p[i_mirror]) : 0; 
     
        // attempt to expand palindrome centered at i
        while(T[i + 1 + p[i]] == T[i - 1 - p[i]])
          ++ p[i];
     
        // If palindrome centered at i expand past R,
        // adjust center based on expanded palindrome,
        if(p[i] + i > R){
          C = i;
          R = i + p[i];
        }
      }
     
      // Find the maximum element in p
      int maxLen = 0;
      int centerIndex = 0;
      for (int i = 1; i < n-1; ++i){
        if(p[i] > maxLen){
          maxLen = p[i];
          centerIndex = i;
        }
      }
      return s.substr((centerIndex - 1 - maxLen)/2 , maxLen);
    }
  • 相关阅读:
    性能测试术语讲解
    Silverlight 部署
    C#数据库SQLServer查询、修改数据
    有一点点背
    Ajax与XMLHttpRequest对象
    ServletListener 之 监听HTTP会话
    JAVA中几种常见集合的使用实例
    [转]全面接触Java集合框架(二)
    自定义标签之 SimpleTag的开发
    jsp常用内置对象
  • 原文地址:https://www.cnblogs.com/myshuangwaiwai/p/4480459.html
Copyright © 2011-2022 走看看