Manacher HDOJ 3068 最长回文

 

题目传送门

关于求解最长回文子串,有dp做法,也有同样n^2的但只用O(1)的空间,还有KMP,后缀数组??

 1 int main(void)    {
 2     while (scanf ("%s", str + 1) == 1)  {
 3         int len = strlen (str + 1);
 4         memset (dp, false, sizeof (dp));
 5         for (int i=1; i<=len; ++i)  dp[i][i] = true;
 6         for (int i=1; i<len; ++i)   {
 7             dp[i][i+1] = (str[i] == str[i+1]);
 8         }
 9         int ans = 1;
10         for (int i=3; i<=len; ++i)  {
11             for (int j=1; j+i-1<=len; ++j)  {
12                 if (dp[j+1][j+i-2] && str[j] == str[j+i-1]) {
13                     dp[j][j+i-1] = true;
14                     ans = max (ans, i);
15                 }
16             }
17         }
18         printf ("%d\n", ans);
19     }
20 
21     return 0;
22 }
n^2

 

但是n^2的复杂度是过不了3068这题,下面用O(n)的算法解决

 

1 waabwswfd
2 pre: waabwswfd len: 9
3 now: $#w#a#a#b#w#s#w#f#d# len: 20
4 pi:  01212321212141212121
5 maxlen: 3
例子帮助理解
 1 /*
 2     题意:求最长回文串(不是最长回文子序列)
 3     Manasher:一个好理解,实现方便,O(n)时间复杂的很屌的算法。
 4         简单说一下原理:首先将原字符串每个相邻之间插入一个不可能在字符串出现的字符,这样可以解决奇偶问题
 5                         然后p[i]表示以i为回文中心,最长的回文长度(单边),然而在原字符串中ans = max p[i] - 1
 6                         我认为算法精髓在于求p[i]时充分利用了回文的性质,跳过了一些无用的扫描。如果不明白上面有例子
 7     详细解释:中文版    英文版
 8 */
 9 /************************************************
10 * Author        :Running_Time
11 * Created Time  :2015-8-7 19:27:46
12 * File Name     :Manacher.cpp
13  ************************************************/
14 
15 #include <cstdio>
16 #include <algorithm>
17 #include <iostream>
18 #include <sstream>
19 #include <cstring>
20 #include <cmath>
21 #include <string>
22 #include <vector>
23 #include <queue>
24 #include <deque>
25 #include <stack>
26 #include <list>
27 #include <map>
28 #include <set>
29 #include <bitset>
30 #include <cstdlib>
31 #include <ctime>
32 using namespace std;
33 
34 #define lson l, mid, rt << 1
35 #define rson mid + 1, r, rt << 1 | 1
36 typedef long long ll;
37 const int MAXN = 1e5 + 10000;
38 const int INF = 0x3f3f3f3f;
39 const int MOD = 1e9 + 7;
40 char s[MAXN], str[MAXN*2];
41 int p[MAXN*2];
42 
43 int Manacher(void)  {
44     str[0] = '$';  str[1] = '#';
45     int len = strlen (s);
46     for (int i=0; i<len; ++i)   {
47         str[i*2+2] = s[i];  str[i*2+3] = '#';
48     }
49     len = len * 2 + 2;  str[len] = '\0';
50     int mx = 0, id = 0;
51     for (int i=1; i<len; ++i)   {
52         if (mx > i) p[i] = min (p[2*id-i], mx - i);
53         else    p[i] = 1;
54         while (str[i-p[i]] == str[i+p[i]])  p[i]++;
55         if (mx < p[i] + i)  {
56             mx = p[i] + i;  id = i;
57         }
58     }
59     int ret = 0;
60     for (int i=0; i<len; ++i)   {
61         ret = max (ret, p[i]);
62     }
63     return ret - 1;
64 }
65 
66 int main(void)    {     //HDOJ 3068 最长回文
67     while (scanf ("%s", s) == 1)  {
68         printf ("%d\n", Manacher ());
69     }
70 
71     return 0;
72 }
posted @ 2015-08-07 20:18  Running_Time  阅读(285)  评论(0编辑  收藏  举报