关于求解最长回文子串,有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 /* 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 }
时间: 2024-10-13 11:45:47