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 };
  • 相关阅读:
    几种比较好看的颜色代码
    浅谈Express的put与del
    关于Linux软连接
    logstash根据日志关键词报警
    linux历史命令审计
    showdoc升级问题,showdoc错误日志
    以Docker容器的形式运行GVM-11
    主机标准化配置文档
    网络设备标准化配置文档
    Zabbix日常监控之lvs监控
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3542201.html
Copyright © 2011-2022 走看看