标签:
经典题,没什么好说的,直接上manacher,时间复杂度O(n),空间复杂度O(n),因为需要额外申请一个数组存储每个位置的子回文长度。
算法精髓:
1.把无论奇,偶长度字符串转换为奇数个。
2.利用已经得到的最长回文的右边界来减少重复计算的次数,如果右边界mx>i,则p[i] = min(mx-i, p[2*id-i]).
hihocoder的测试数据可能比较大,如果直接用C++的string拼接字符串直接就TLE了,很好奇为什么没有用右值引用优化,居然在构造阶段就超时了,
无奈只能换成字符数组。
Impl:
1 #include <string> 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 char* preProcess(char* str, char* tstr) 9 { 10 int len = strlen(str); 11 int j = 0; 12 tstr[j++] = ‘#‘; 13 for (int i = 0; i < len; ++i) { 14 tstr[j++] = str[i]; 15 tstr[j++] = ‘#‘; 16 } 17 tstr[j++] = ‘$‘; 18 tstr[j] = ‘\0‘; 19 return tstr; 20 } 21 22 23 int manacher(char* str, char* str1) 24 { 25 char* tstr = preProcess(str, str1); 26 int len = strlen(tstr); 27 if (len == 2) return 0; 28 29 int mx = 0, id; 30 int* p = new int[len]; 31 for (int i = 1; i < len-1; ++i) 32 { 33 p[i] = i < mx ? min(mx-i, p[2*id-i]) : 0; 34 35 while (tstr[i+p[i]+1] == tstr[i-p[i]-1]) 36 p[i]++; 37 38 if (p[i]+i > mx) 39 { 40 id = i, mx = p[i]+i; 41 } 42 } 43 44 int maxLen=1; 45 for (int i = 1; i < len-1; ++i) 46 maxLen = max(maxLen, p[i]); 47 delete [] p; 48 return maxLen; 49 } 50 51 char str[1000010]; 52 char tstr[2000020]; 53 54 int main() 55 { 56 int n; 57 scanf("%d", &n); 58 59 while (n--) 60 { 61 scanf("%s", str); 62 printf("%d\n", manacher(str, tstr)); 63 } 64 65 return 0; 66 }
标签:
原文地址:http://www.cnblogs.com/sheepsheep/p/4416446.html