Hdu 5371 Hotaru's problem (manacher+枚举)
题目链接:
题目描述:
给出一个字符串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 }
本文为博主原创文章,未经博主允许不得转载。