题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4513
题目描述:
打完题目描述了,点开题目,发现题目是中文,orz.jpg。果断又删掉了,习惯真可怕.......
解题思路:
刚开始,我先manacher求出以 i 为中心的回文串半径存入vis,然后暴力循环每一个位置是不是最长的完美队列。果断T了,胡乱改了几处依旧T。突然灵机一动,发现可以在跑vis数组的时候加一些判定条件,然后直接求出max(vis[i])即可。
学习算法是次要,理解算法思想,锻炼思维灵敏逻辑缜密才最重要。
1 #include <cstdio> 2 #include <string> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #include <queue> 8 using namespace std; 9 10 typedef long long LL; 11 const int maxn = 100010; 12 int vis[maxn*2], a[maxn], b[maxn*2]; 13 14 bool judge (int x, int y) 15 { 16 for (int i=x+1; i<=y/2; i++) 17 if (a[i]<a[i-1]) 18 return false; 19 return true; 20 } 21 22 void manacher (int s[], int len) 23 { 24 int l = 0; 25 b[l ++] = -100; 26 b[l ++] = -1; 27 28 for (int i=0; i<len; i++) 29 { 30 b[l ++] = a[i]; 31 b[l ++] = -1; 32 } 33 b[l] = 0; 34 35 int mx = 0, id = 0, ans = 0; 36 37 for (int i=0; i<l; i++) 38 { 39 vis[i] = mx > i ? min (vis[2*id-i], mx-i):1; 40 41 while (b[i-vis[i]] == b[i+vis[i]] && (b[i-vis[i]]==-1 || b[i-vis[i]]<=b[i-vis[i]+2])) vis[i] ++; 42 43 if (i + vis[i] > mx) 44 { 45 mx = i + vis[i]; 46 id = i; 47 } 48 ans = max (ans, vis[i]); 49 } 50 51 52 printf ("%d ", ans - 1); 53 } 54 55 int main () 56 { 57 int T, n; 58 scanf ("%d", &T); 59 60 while (T --) 61 { 62 scanf ("%d", &n); 63 for (int i=0; i<n; i++) 64 scanf ("%d", &a[i]); 65 66 manacher(a, n); 67 } 68 return 0; 69 }