LeetCode - Longest Palindromic Substring

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 };

 

转载于:https://www.cnblogs.com/zhuli19901106/p/3542201.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值