Hdu 4513 吉哥系列故事——完美队形II (manacher变形)

题目链接:

  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\n", 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 }

 

posted @ 2016-04-25 20:20  罗茜  阅读(507)  评论(0编辑  收藏  举报