1. 程式人生 > >HDU 5371 (2015多校聯合訓練賽第七場1003)Hotaru's problem(manacher+二分/枚舉)

HDU 5371 (2015多校聯合訓練賽第七場1003)Hotaru's problem(manacher+二分/枚舉)

2015多校 while bre 算法 down ice man 暴力 turn

pid=5371">HDU 5371

題意:

定義一個序列為N序列:這個序列按分作三部分,第一部分與第三部分同樣,第一部分與第二部分對稱。


如今給你一個長為n(n<10^5)的序列,求出該序列中N序列的最大長度。

思路:

來自官方題解:修正了一些題解錯別字(誤

先用求回文串的Manacher算法。求出以第i個點為中心的回文串長度。記錄到數組p中

要滿足題目所要求的內容。須要使得兩個相鄰的回文串,共享中間的一部分,也就是說。左邊的回文串長度的一半,要大於等於共享部分的長度,右邊回文串也是一樣。 由於我們已經記錄下來以第i個點為中心的回文串長度, 那麽問題能夠轉化成,相距x的兩個數a[i],a[i+x],滿足p[i]/2>=x 而且 p[i+x]/2>=x。要求x盡量大

這能夠用一個set維護。一開始集合為空,依次取出p數組中最大的元素。將其下標放入set中,每取出一個元素,在該集合中二分查找比i+p[i]/2小,但最大的元素。更新ans。

然後查找集合中比i-p[i]/2大,但最小的元素,更新ans。

答案就是3*ans

嗯~事實上不用二分暴力掃下也能水過去

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath> #include<algorithm> #include<string> #include<map> #include<set> #include<vector> #include<queue> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define mp make_pair #define pb push_back
typedef long long lint; typedef long long ll; typedef long long LL; const int maxn = 100000 + 5; int p[2*maxn]; int s[maxn]; int s1[2*maxn]; int n; void init(){ cls(s1); s1[0] = -1; s1[1] = -2; int k = 2; for(int i = 0 ; i < n ; i++){ s1[k++] = s[i]; s1[k++] = -2; } } void manacher(){ int mx = 0 , id = 0; p[0] = 0; for(int i = 0 ; i < 2*n+1 ; i++){ if(mx > i) p[i] = min(p[2*id-i] , mx-i); else p[i] = 1; while(s1[i-p[i]] == s1[i+p[i]]) p[i]++; if(mx < p[i]+i){ mx = p[i] + i; id = i; } } } int solve(){ int ans = 0; for(int i = 1; i < n*2 + 1 ; i += 2) if((p[i] - 1) / 2 > ans){ for(int j = i + p[i] - 1 ; ; j -= 2){ if(p[j] >= j-i){ ans = (j-i) / 2; break; } if((j-i)/2 <= ans) break; } } return 3*ans; } int main(){ //freopen("input.txt","r",stdin); int t; cin >> t ; int kase = 1; while(t--){ cls(s);cls(p);cls(s1); cin >> n; for(int i = 0 ; i < n ; i++){ scanf("%d",s+i); } init(); manacher(); printf("Case #%d: %d\n",kase++,solve()); } return 0; }

HDU 5371 (2015多校聯合訓練賽第七場1003)Hotaru&#39;s problem(manacher+二分/枚舉)