HDU 4513 吉哥系列故事——完美队形II Manacher算法
http://acm.hdu.edu.cn/showproblem.php?pid=4513
题意:
找出给定的序列中最长的回文串,但有一个要求,必须是从左边到中间中的每一个数字,左边的都要
小于等于右边的,而中间到右边的则相反。
坑爹:
如果暴力的话要O(n^2) 而n最大能到100000,所以暴力是不行的。
解法:
Manacher的算法的模板,大约复杂度为O(n)。

1 #include<iostream> 2 using namespace std; 3 4 const int maxn = 110000 + 10; 5 const int INF = 0x3fffffff; 6 7 int str[maxn]; 8 int s[2*maxn]; 9 int p[2*maxn]; 10 int Max; 11 int n; 12 int j; 13 14 void init() 15 { 16 Max = 0; 17 memset(p,0,sizeof(p)); 18 memset(s,0,sizeof(s)); 19 } 20 21 void Manacher() 22 { 23 int i; 24 int mx = 0; 25 int id; 26 int len = j; 27 for(i=1; i<len; i++) 28 { 29 if(mx > i) 30 { 31 p[i] = min(p[2*id-i], mx-i); 32 } 33 else 34 { 35 p[i] = 1; 36 } 37 int m = s[i]; 38 if(s[i] == INF) 39 { 40 m = s[i+1] > s[i-1] ? s[i+1] : s[i-1]; 41 } 42 for(;s[i+p[i]] == s[i-p[i]]; p[i]++) 43 { 44 if(s[i+p[i]] == INF) 45 { 46 continue; 47 } 48 if(m >= s[i+p[i]]) 49 { 50 m = s[i+p[i]]; 51 } 52 else 53 { 54 break; 55 } 56 } 57 58 if(Max < p[i]) 59 { 60 Max = p[i]; 61 } 62 63 if(p[i] + i > mx) 64 { 65 mx = p[i] + i; 66 id = i; 67 } 68 } 69 } 70 71 int main() 72 { 73 int T; 74 scanf("%d",&T); 75 while(T--) 76 { 77 init(); 78 scanf("%d",&n); 79 int i; 80 for(i=0; i<n; i++) 81 { 82 scanf("%d",&str[i]); 83 } 84 j = 0; 85 s[j++] = INF; 86 for(i=0; i<n; i++) 87 { 88 s[j++] = INF; 89 s[j++] = str[i]; 90 } 91 s[j++] = INF; 92 93 Manacher(); 94 95 printf("%d\n",Max-1); 96 } 97 return 0; 98 }