zoukankan      html  css  js  c++  java
  • LeetCode

    Longest Palindromic Substring

    2014.2.10 00:57

    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.

    Solution1:

      My first solution to this problem is the brute-force version, with O(n^2) time complexity, where n is the length of the string.

      The code needs no further explanation, please see for yourself.

      Time complexity is O(n^2), space complexity is O(1).

    Accepted code:

     1 // 1AC, the brute-force solution, O(n^2) time complexity
     2 class Solution {
     3 public:
     4     string longestPalindrome(string s) {
     5         int i, j;
     6         int len;
     7         int ll, rr;
     8         string s1, s2;
     9         string str;
    10         
    11         len = (int)s.length();
    12         if (len <= 1) {
    13             return s;
    14         }
    15         s1 = "";
    16         for (i = 0; i < len; ++i) {
    17             j = 0;
    18             while (true) {
    19                 if ((i - j < 0) || (i + j > len - 1) || (s[i - j] != s[i + j])) {
    20                     break;
    21                 } else {
    22                     ++j;
    23                 }
    24             }
    25             --j;
    26             if (2 * j + 1 > (int)s1.length()) {
    27                 s1 = s.substr(i - j, 2 * j + 1);
    28             }
    29         }
    30         s2 = "";
    31         for (i = 0; i < len - 1; ++i) {
    32             j = 0;
    33             while (true) {
    34                 if ((i - j < 0) || (i + 1 + j > len - 1) || (s[i - j] != s[i + 1 + j])) {
    35                     break;
    36                 } else {
    37                     ++j;
    38                 }
    39             }
    40             --j;
    41             if (2 * j + 2 > (int)s2.length()) {
    42                 s2 = s.substr(i - j, 2 * j + 2);
    43             }
    44         }
    45         
    46         if (s1.length() > s2.length()) {
    47             return s1;
    48         } else {
    49             return s2;
    50         }
    51     }
    52 };

    Solution2:

      I believe you've heard about the Manacher's Algorithm. It is an efficient solution to this problem, which is linear and one-pass. Perhaps you haven't tried it yourself. Here is the wiki for your information: Manacher's Algorithm.

      The difference between Manacher's Algorithm and the Brute-Force one can be described with an example below:

        1. Here is a string "....sabcbas....", the part I show you here is a palindrome.

        2. 'c' is the center of that palindrome, and the two 's's are symmetric, with 'c' as the symmetric center.

        3. If this palindromic string is currently the longest we can find, and we're currently standing at the position of the second 's'.

        4. We see that "sabc" and "cbas" look symmetric, and we suppose that the longest palindrome you can get with the second 's' as the center might be similar to the first 's', since they're symmetric.

        5. Since the algorithm runs in one pass, we've know everything before s[i] when we're at position i.

        6. The right side of the first 's' is already known, so is the left side of the second 's'. No more matching is needed here. That's why this algorithm can save some duplicated matching.

        7. Nevertheless, the right part of "..." is still unknown, thus the matching must still be done here.

        8. If a longer palindrome is found, the center 'c' and the palindromic radius will be updated.

        9. The algorithm won't recalculate the palindrome within that longest palindromic range, that is, the farthest position the currently longest palindrome can reach. That's why the code has double loops, but still runs in O(n) time.

      You might find the descriptions above a total mess. I have to say it really wasn't easy for me to digest the code when learning this genius algorithm.

      The great Einstein once said, "if you can't explain it simply you don't understand it well enough". Guess that's why I tried to put a lot of words only to get you confused here. You might look at the code below, it's much simpler than my broken English. (^_^)

      Besides the algorithm description, there's one more thing to mention. To treat cases like "abba" and "aba", you don't have to write two copies of code, just insert some delimiter like '#' between every character will solve the problem.

      One last thing, this version of code put an extra character at the front, purely for the convenience of coding. If you've got your own way to make the code look short and clean, please share it with me.

      Time and space complexities are both O(n).

    Accepted code:

     1 // 1CE, 2WA, 1AC, this really wasn't easy to understand..
     2 class Solution {
     3 public:
     4     string longestPalindrome(string s) {
     5         int len = (int)s.length();
     6         int nlen;
     7         int i, j;
     8         char *ss;
     9         int *p;
    10         
    11         nlen = 2 * len + 2;
    12         ss = new char[nlen + 1];
    13         p = new int[nlen + 1];
    14         
    15         // insert '#' between every character.
    16         nlen = 0;
    17         ss[nlen++] = '$';
    18         for (i = 0; i < len; ++i) {
    19             ss[nlen++] = '#';
    20             ss[nlen++] = s[i];
    21         }
    22         ss[nlen++] = '#';
    23         ss[nlen] = 0;
    24         
    25         // the farthest position the current palindromic string can reach.
    26         int mx_pos;
    27         // the index i that reaches this farthest position.
    28         int id;
    29         
    30         // the Manacher algorithm
    31         p[0] = 0;
    32         mx_pos = 0;
    33         for (i = 1; i < nlen; ++i) {
    34             p[i] = 1;
    35             if (mx_pos > i) {
    36                 p[i] = p[2 * id - i];
    37                 if (mx_pos - i < p[i]) {
    38                     p[i] = mx_pos - i;
    39                 }
    40             }
    41             
    42             while (ss[i - p[i]] == ss[i + p[i]]) {
    43                 ++p[i];
    44             }
    45             
    46             if (i + p[i] > mx_pos) {
    47                 mx_pos = i + p[i];
    48                 id = i;
    49             }
    50         }
    51         
    52         // find the maximal value
    53         int result = 0;
    54         int ri;
    55         string res_str;
    56         char *res;
    57         res = new char[len + 1];
    58         for (i = 0; i < nlen; ++i) {
    59             if (p[i] > result) {
    60                 ri = i;
    61                 result = p[i];
    62             }
    63         }
    64         
    65         len = 0;
    66         for (i = ri - p[ri] + 1; i <= ri + p[ri] - 1; ++i) {
    67             if ((i > 0) && ((i & 0x1) == 0)) {
    68                 // odd positions are inserted with '#'
    69                 // 0th position is inserted with '$'
    70                 res[len++] = ss[i];
    71             }
    72         }
    73         res[len] = 0;
    74         res_str = string(res);
    75         
    76         delete [] res;
    77         delete [] p;
    78         delete [] ss;
    79         
    80         return res_str;
    81     }
    82 };
  • 相关阅读:
    使用remove_constants工具查看Oracle是否使用绑定变量
    v$sqlarea,v$sql,v$sqltext这三个视图提供的sql语句有什么区别?
    Cardinality (基数)
    分区表操作
    递归连接查询
    解决Android应用安装快完毕时提示签名冲突,android签名文件生成(转)
    Oracle的Numer类型与C,C#数据类型对应关系
    Spring学习(四)——使用Spring JDBC访问数据库
    Spring学习(三)——集成 Velocity
    Spring学习(二)——使用Gradle构建一个简单的Spring MVC Web应用程序
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3542201.html
Copyright © 2011-2022 走看看