ural1297 Palindrome【后缀数组】
2015-04-25 12:06
405 查看
题意:给出一个串,求出这个串的最长回文字串。
用后缀数组解决,把这个串反向并接在原串后面,中间加一个没有出现过的字符。然后枚举回文字串的中心(这里要按串的长度分成奇数长度和偶数长度),求这个枚举的位置和在反向接上去的那个位置,这两个位置之间的最长公共前缀就可以了。。求公共前缀用个线段树维护就好了
用后缀数组解决,把这个串反向并接在原串后面,中间加一个没有出现过的字符。然后枚举回文字串的中心(这里要按串的长度分成奇数长度和偶数长度),求这个枚举的位置和在反向接上去的那个位置,这两个位置之间的最长公共前缀就可以了。。求公共前缀用个线段树维护就好了
#include<cstdio> #include<cstring> #include<algorithm> #define ls (k<<1) #define rs (k<<1|1) using namespace std; const int MAXN=2010; int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN]; bool cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=r[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; p=1; for(j=1;p<n;j<<=1) { p=0; for(i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++; m=p; } } int height[MAXN],RANK[MAXN]; void calheight(int *r,int *sa,int n) { int i,j,k=0; for(i=0;i<=n;i++) RANK[sa[i]]=i; for(i=0;i<n;i++) { if(k) k--; j=sa[RANK[i]-1]; while(r[i+k]==r[j+k]) k++; height[RANK[i]]=k; } } struct TREE { int l,r; int val; int mid() { return (l+r)>>1; } }tree[MAXN<<2]; void pushup(int k) { tree[k].val=min(tree[ls].val,tree[rs].val); } void build(int l,int r,int k) { tree[k].l=l; tree[k].r=r; if(l==r) { tree[k].val=height[l]; return; } int mid=tree[k].mid(); build(l,mid,ls); build(mid+1,r,rs); pushup(k); } int query(int l,int r,int k) { if(l>r) return 1; if(tree[k].l>=l&&tree[k].r<=r) return tree[k].val; int mid=tree[k].mid(); if(r<=mid) return query(l,r,ls); else if(l>mid) return query(l,r,rs); else return min(query(l,mid,ls),query(mid+1,r,rs)); } int r[MAXN],sa[MAXN]; char str[MAXN]; int main() { int i,n; while(scanf("%s",str)==1) { n=strlen(str); for(i=0;i<n;i++) r[i]=str[i]; r ='$'; for(i=n+1;i<=2*n;i++) { r[i]=str[2*n-i]; } r[2*n+1]=0; da(r,sa,2*n+2,129); calheight(r,sa,2*n+1); build(1,2*n+1,1); int ans=-2,l,rr,w,u,v; for(i=0;i<n;i++) { if(i==59) i=59; u=min(RANK[i],RANK[2*n-i]);v=max(RANK[i],RANK[2*n-i]); int temp=query(u+1,v,1); w=temp*2-1; if (w>ans) { ans=w; l=i-temp+1; rr=i+temp-1; } u=min(RANK[i],RANK[2*n-i+1]);v=max(RANK[i],RANK[2*n-i+1]); temp=query(u+1,v,1); w=temp*2; if (w>ans) { ans=w; l=i-temp; rr=i+temp-1; } } for(i=l;i<=rr;i++) printf("%c",str[i]); printf("\n"); } return 0; } /* ThesampletextthatcouldbereadedthesameinbothordersArozaupalannalapuazorA */
相关文章推荐
- URAL 1297. Palindrome(后缀数组 求最长回文子串)
- URAL 1297 Palindrome 后缀数组 或 Manacher 求最长回文子串
- URAL 1297. Palindrome(后缀数组求最大回文串)
- ural 1297 Palindrome (后缀数组 最长回文)
- 【后缀数组|最长回文子串】URAL-1297 Palindrome
- URAL - 1297 Palindrome(后缀数组求最长回文子串)
- URAL 1297 Palindrome(后缀数组求最长回文子串)
- 【后缀数组】【URAL 1297】Palindrome
- URAL 1297 Palindrome【后缀数组】求最长回文子串
- Ural1297(Palindrome)求最长回文子串(后缀数组)
- ural 1297 Palindrome求最长连续回文子串(后缀数组求法)
- URAL 1297 Palindrome(最长回文子串:后缀数组)
- 【后缀数组】【最长回文子串】Palindrome Ural_1297
- URAL 1297:后缀数组求最长回文串
- ural 1297 后缀数组 最长回文子串
- ural 1297 后缀数组求最长回文子串
- URAL1297------后缀数组
- URAL 1297 后缀数组:求最长回文子串
- 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297
- ural 1297 后缀数组求最长回文串