bzoj 2342 [Shoi2011]双倍回文(manacher,set)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=2342
【题意】
求出形如w wR w wR的最长连续子串。
【思路】
用manacher算法计算出p[],表示以i与i+1为中心的最长回文字串长度/2
枚举第一个wR的结束位置x,当且仅当y-p[y]<=x且y<=x+p[x]/2子串[x+1,y]是一个答案,更新ans。
满足的条件是一个二维偏序,按照y-p[y]排序,在查询x之前保证将所有满足第一个式子的x'加入set,查询时找到x+p[x]/2在set中的前驱即为最大的答案。
【代码】
1 #include<set> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 5e5+10; 8 9 set<int> t; 10 set<int> ::iterator it; 11 12 char s[N]; 13 int n,ans,p[N],q[N]; 14 15 bool cmp(int a,int b) 16 { 17 return (a-p[a])<(b-p[b]); 18 } 19 20 void manacher() 21 { 22 int mx=0,id; 23 for(int i=1;i<=n;i++) 24 { 25 if(mx>=i)p[i]=min(mx-i,p[2*id-i]); 26 else 27 p[i]=0; 28 while(s[i+p[i]+1]==s[i-p[i]]) p[i]++; 29 if(p[i]+i>mx)id=i,mx=p[i]+i; 30 } 31 } 32 33 int main() 34 { 35 scanf("%d%s",&n,s+1); 36 s[0]='#'; 37 manacher(); 38 for(int i=1;i<=n;i++) q[i]=i; 39 sort(q+1,q+n+1,cmp); 40 int now=1; 41 for(int i=1;i<=n;i++) 42 { 43 while(now<=n&&q[now]-p[q[now]]<=i) 44 t.insert(q[now++]); 45 it=t.upper_bound(i+p[i]/2); 46 if(it!=t.begin()) 47 ans=max(ans,(*--it-i)*4); 48 } 49 printf("%d\n",ans); 50 return 0; 51 }
P.S. 新姿势[马拉车]解锁 :)
posted on 2016-04-02 23:46 hahalidaxin 阅读(512) 评论(0) 编辑 收藏 举报