您的位置:首页 > 其它

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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: