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的复杂度是过不了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 }
编译人生,运行世界!