Hdu 5371 Hotaru's problem (manacher+枚举)

题目链接:

  Hdu 5371 Hotaru's problem

题目描述:

  给出一个字符串N,要求找出一条N的最长连续子串。这个子串要满足:1:可以平均分成三段,2:第一段和第三段相等,3:第一段和第二段回文。

解题思路:
  其实通俗来讲就是求符合题意的最长回文串。先用manacher与处理一下字符串N,得出以n[i]与n[i+1]为中心的回文串长度半径记为p[i],然后循环枚举i作为第一段的终点,p[i]+i-1作为第二段的终点记做j。当p[i]>=(j-i+1)&&p[j]>=(j-i+1)时,这个枚举区间[i, j]才算合法,然后比较求出最大区间长度即可。

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 100005;
 9 int a[maxn*2], p[maxn*2], n;
10 
11 void manather ()
12 {
13     
14     for (int i=n; i>0; i--)
15     {
16         a[i*2  ] = a[i];
17         a[i*2-1] = -2;
18     }
19     
20     n = n * 2 + 1;
21     a[0] = -1;
22     a[n] = -2;
23     int x = 0;
24     
25     for (int i=2; i<n; i++)
26     {
27         
28         if (p[x]+x > i)
29             p[i] = min (p[2*x-i], p[x]-i+x);
30         else
31             p[i] = 1;
32             
33         while (a[i-p[i]] == a[i+p[i]])
34             p[i] ++;
35             
36         if (x+p[x] < i+p[i])
37             x = i;
38     }
39 }
40 int main ()
41 {
42     int t, l = 0;
43     scanf ("%d", &t);
44     
45     while (t --)
46     {
47         scanf ("%d", &n);
48         
49         for (int i=1; i<=n; i++)
50             scanf ("%d", &a[i]);
51             
52         manather();
53         int ans = 0;
54         
55         for (int i=1; i<=n; i+=2)
56             for (int j=i+p[i]-1; j-i>ans; j-=2)
57                 if (p[j]>=j-i+1 && ans < j-i)
58                 {
59                     ans = j - i;
60                     break;
61                 }
62                 
63         printf ("Case #%d: %d\n", ++l, ans/2*3);
64     }
65     
66     return 0;
67 }

 

posted @ 2015-08-12 09:12  罗茜  阅读(191)  评论(0编辑  收藏  举报