最长回文子串(ural1297)
2010-09-07 09:32
281 查看
解决回文类问题 。 转化为后缀数组的方法是自己想到的 这个还是比较不错。
虽然 $符号的设置是看了以下解题报告。不过 具体用法是自己想到的再接再厉哦 。
这道题算是打补丁 打过去的,开始是没有注意 用求 公共祖先来求得最长匹配串(这里是rmq问题,写成了求h最大,应该是求h数组u最小)。然后是奇数串 和偶数串也有所不同。
然后求最先情况也没有 处理好 。思路一定要清晰,要想好。不然会浪费很多时间。
贴代码以后总结成为模板
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
#define e 40100
int a[e],sa[e],container[e],wy[e],wv[e],wx[e],rrank[e],h[e];
char b[e];
int cmp(int *r,int a,int b,int l)
{
return (r[a]==r[b])&&(r[a+l]==r[b+l]);
}
void suffix(int *r,int n,int *sa,int m)
{
int i,j,*t,*x=wx, *y=wy,p;
memset(container,0,sizeof(int)*m);
for(i=0; i<n; i++) container[x[i]=r[i]]++;
for(i=1; i<m; i++) container[i]+=container[i-1];
for(i=n-1; i>=0; i--) sa[--container[x[i]]]=i;
for(p=0,j=1; p<n; j<<=1,m=p)
{
for(p=0,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]];
memset(container,0,sizeof(int)*m);
for(i=0; i<n; i++) container[wv[i]]++;
for(i=1; i<m; i++) container[i]+=container[i-1];
for(i=n-1; i>=0; i--) sa[--container[wv[i]]]=y[i];
for(t=x,x=y,y=t,x[sa[0]]=0,p=1, i=1; i<n; i++)
x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
}
}
void cal(int *r,int *sa,int n)
{
int i,j,k=0;
for(i=1; i<=n; i++) rrank[sa[i]]=i;
for(i=0; i<n; h[rrank[i++]]=k)
for(k?k--:0,j=sa[rrank[i]-1]; r[i+k]==r[j+k]; k++);
}
int fmax[e][20];
void makermq(int n)//rmq 问题模板
{
int i,j,k;
for(i=1; i<=n; i++) fmax[i][0]=h[i];
for(j=1; (1<<j)<=n; j++)
{
k=1<<(j-1);
for(i=1; i+k<=n ;i++)
{
fmax[i][j]=min(fmax[i][j-1],fmax[i+k][j-1]);
}
}
}
int findmax(int l,int r)//查找rmq问题模板
{
int k=1;
if(l>r)swap(l,r);
l++;
int dis=r-l+1;
for(k=0; (1<<k)<=dis; k++);
k--;
int x=fmax[l][k];
if(fmax[r-(1<<k)+1][k]<=x)return fmax[r-(1<<k)+1][k];
return x;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("//home//mabodx//桌面//in.txt","r",stdin);
#endif
int n;int i;
while(cin>>b)
{
n=strlen(b);
int len= n*2;
for(i=0; i<n; i++)
{
a[i]=a[len-i]=b[i];
}
a
=1;//////////////////////////////////这个字符要怎么处理
len++;
a[len]=0;
suffix(a,len+1,sa,301);
cal(a,sa,len);
makermq(len);
int maxx=-1;
int q,r;int j;int flag=1;
int ll=-1;
for(i=0; i< n ;i++)
{
r=findmax(rrank[i],rrank[2*n-i])-1;
if(ll<r*2+1)
{
ll=r*2+1;
maxx=r;
flag=1;
q=i;
}
r=findmax(rrank[i],rrank[2*n-i+1]);
if(ll<r*2)
{
ll=r*2;
maxx=r;
flag=2;
q=i;
}
}
if(flag==1)
{
for(i=q-maxx,j=0;j<maxx*2+1; j++,i++ )
printf("%c",b[i]);cout<<endl;
}
else
{
for(i=q-maxx,j=0; j<maxx*2; j++,i++)
printf("%c",b[i]);cout<<endl;
}
}
}
虽然 $符号的设置是看了以下解题报告。不过 具体用法是自己想到的再接再厉哦 。
这道题算是打补丁 打过去的,开始是没有注意 用求 公共祖先来求得最长匹配串(这里是rmq问题,写成了求h最大,应该是求h数组u最小)。然后是奇数串 和偶数串也有所不同。
然后求最先情况也没有 处理好 。思路一定要清晰,要想好。不然会浪费很多时间。
贴代码以后总结成为模板
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
#define e 40100
int a[e],sa[e],container[e],wy[e],wv[e],wx[e],rrank[e],h[e];
char b[e];
int cmp(int *r,int a,int b,int l)
{
return (r[a]==r[b])&&(r[a+l]==r[b+l]);
}
void suffix(int *r,int n,int *sa,int m)
{
int i,j,*t,*x=wx, *y=wy,p;
memset(container,0,sizeof(int)*m);
for(i=0; i<n; i++) container[x[i]=r[i]]++;
for(i=1; i<m; i++) container[i]+=container[i-1];
for(i=n-1; i>=0; i--) sa[--container[x[i]]]=i;
for(p=0,j=1; p<n; j<<=1,m=p)
{
for(p=0,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]];
memset(container,0,sizeof(int)*m);
for(i=0; i<n; i++) container[wv[i]]++;
for(i=1; i<m; i++) container[i]+=container[i-1];
for(i=n-1; i>=0; i--) sa[--container[wv[i]]]=y[i];
for(t=x,x=y,y=t,x[sa[0]]=0,p=1, i=1; i<n; i++)
x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
}
}
void cal(int *r,int *sa,int n)
{
int i,j,k=0;
for(i=1; i<=n; i++) rrank[sa[i]]=i;
for(i=0; i<n; h[rrank[i++]]=k)
for(k?k--:0,j=sa[rrank[i]-1]; r[i+k]==r[j+k]; k++);
}
int fmax[e][20];
void makermq(int n)//rmq 问题模板
{
int i,j,k;
for(i=1; i<=n; i++) fmax[i][0]=h[i];
for(j=1; (1<<j)<=n; j++)
{
k=1<<(j-1);
for(i=1; i+k<=n ;i++)
{
fmax[i][j]=min(fmax[i][j-1],fmax[i+k][j-1]);
}
}
}
int findmax(int l,int r)//查找rmq问题模板
{
int k=1;
if(l>r)swap(l,r);
l++;
int dis=r-l+1;
for(k=0; (1<<k)<=dis; k++);
k--;
int x=fmax[l][k];
if(fmax[r-(1<<k)+1][k]<=x)return fmax[r-(1<<k)+1][k];
return x;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("//home//mabodx//桌面//in.txt","r",stdin);
#endif
int n;int i;
while(cin>>b)
{
n=strlen(b);
int len= n*2;
for(i=0; i<n; i++)
{
a[i]=a[len-i]=b[i];
}
a
=1;//////////////////////////////////这个字符要怎么处理
len++;
a[len]=0;
suffix(a,len+1,sa,301);
cal(a,sa,len);
makermq(len);
int maxx=-1;
int q,r;int j;int flag=1;
int ll=-1;
for(i=0; i< n ;i++)
{
r=findmax(rrank[i],rrank[2*n-i])-1;
if(ll<r*2+1)
{
ll=r*2+1;
maxx=r;
flag=1;
q=i;
}
r=findmax(rrank[i],rrank[2*n-i+1]);
if(ll<r*2)
{
ll=r*2;
maxx=r;
flag=2;
q=i;
}
}
if(flag==1)
{
for(i=q-maxx,j=0;j<maxx*2+1; j++,i++ )
printf("%c",b[i]);cout<<endl;
}
else
{
for(i=q-maxx,j=0; j<maxx*2; j++,i++)
printf("%c",b[i]);cout<<endl;
}
}
}
相关文章推荐
- 【URAL】1297 Palindrome 【后缀数组+RMQ——求最长回文子串】
- ural1297 求最长回文子串 | 后缀数组
- URAL 1297 最长回文子串(后缀数组)
- ural 1297 后缀数组 最长回文子串
- URAL 1297 最长回文子串(后缀数组)
- [ural1297]最长回文子串
- ural 1297(求最长回文子串,后缀数组)
- Ural 1297 Palindrome(后缀数组+最长回文子串)
- 【URAL 1297】Palindrome 最长回文子串
- URAL 1297 Palindrome(后缀数组求最长回文子串)
- URAL 1297 Palindrome (最长回文子串)
- ural 1297 最长回文子串
- Ural1297(Palindrome)求最长回文子串(后缀数组)
- URAL 1297 后缀数组+RMQ求串的最长回文子串
- URAL-1297 Palindrome (最长回文子串)
- Ural1297 最长回文子串(后缀数组+RMQ)
- URAL 1297. Palindrome(后缀数组 求最长回文子串)
- HDU3068 URAL1297 Manacher求最长回文子串
- URAL 1297 后缀数组:求最长回文子串
- URAL 1297 Palindrome(最长回文子串 )