题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文。

思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能出现的字符隔开。然后就用到后缀数组的性质了,

我们枚举每一个原始字符串中的字符以它为中心(分为奇数和偶数两种情况)进行查找,比如对于下标为i的字符,当回文串为奇数时,我们要求的就是i的后缀与2*n-i的

后缀的最长公共前缀了,然后根据height数组的性质就转化成求height[i+1]...height[2*n-i]中的最小值了,这时我们想到了用RMQ求区间最值了,对于不会RMQ的童

鞋可以先去学习下,再来做这道题,具体看代码实现:

代码实现:

#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
#define N 2010
int ws1[N],wv[N],wa[N],wb[N];
int rank1[N],height[N],sa[N];
char str[N];
int a[N],n;
int dp[N][]; int min(int a,int b)
{
return a>b?b:a;
} int 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,*t;
for(i=;i<m;i++)
ws1[i]=;
for(i=;i<n;i++)
ws1[x[i]=r[i]]++;
for(i=;i<m;i++)
ws1[i]+=ws1[i-];
for(i=n-;i>=;i--)
sa[--ws1[x[i]]]=i;
for(j=,p=;p<n;j*=,m=p)
{
for(p=,i=n-j;i<n;i++)
y[p++]=i;
for(i=;i<n;i++)
if(sa[i]>=j)
y[p++]=sa[i]-j;
for(i=;i<n;i++)
wv[i]=x[y[i]];
for(i=;i<m;i++)
ws1[i]=;
for(i=;i<n;i++)
ws1[wv[i]]++;
for(i=;i<m;i++)
ws1[i]+=ws1[i-];
for(i=n-;i>=;i--)
sa[--ws1[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
} void calheight(int *r,int *sa,int n)
{
int i,j,k=;
for(i=;i<=n;i++)
rank1[sa[i]]=i;
for(i=;i<n;height[rank1[i++]]=k)
for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++) ;
} void RMQ()//RMQ预处理
{
int i,j;
memset(dp,,sizeof(dp));
for(i=;i<=n*+;i++)
dp[i][]=height[i];
for(j=;(<<j)<=*n+;j++)
for(i=;i+(<<j)-<=*n+;i++)
dp[i][j]=min(dp[i][j-],dp[i+(<<(j-))][j-]);
} int lcp(int l,int r)//求最长公共前缀
{
int a=rank1[l],b=rank1[r];
if(a>b)
swap(a,b);
a++;
int t=(int)(log(double(b-a+))/log(2.00));
return min(dp[a][t],dp[b-(<<t)+][t]);
} int main()
{
int i,res,flag,max;
while(scanf("%s",str)!=EOF)
{
max=;
n=strlen(str);
for(i=;i<n;i++)
a[i]=(int)str[i];
a[n]=;
for(i=;i<n;i++)
a[i+n+]=int(str[n-i-]);
a[*n+]=;
da(a,sa,n*+,);
calheight(a,sa,*n+);
RMQ();
for(i=;i<n;i++)
{
res=lcp(i,*n-i)*-;
if(max<res)//奇数时
{
max=res;
flag=i;
}
if(i>)//偶数时
{
res=lcp(i,*n-i+)*;
if(max<res)
{
max=res;
flag=i;
}
}
}
if(max%==)
for(i=flag-max/;i<=flag+max/;i++)
printf("%c",str[i]);
else
for(i=flag-max/;i<=flag+max/-;i++)
printf("%c",str[i]);
printf("\n");
}
return ;
}

最新文章

  1. 清除SQL2008R2日志文件
  2. Linux 设备驱动程序 proc seq
  3. 使用网易ubuntu镜像加速软件包安装
  4. Nginx+uWSGI+Django+Python+ MySQL 搭建可靠的Python Web服务器
  5. Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面 z
  6. 检测网页是否可以打开, 再使用IE打开网页
  7. [Android]应用的前后台运行
  8. configSections(配置文件)
  9. document.write 存在几个问题?应该注意
  10. 用KMP算法实现strStr()
  11. BigInteger类及方法应用
  12. springboot打成jar后文件读取问题
  13. 【原创】从策略模式闲扯到lambda表达式
  14. 第213天:12个HTML和CSS必须知道的重点难点问题
  15. SQL注入学习资料总结
  16. 9、BOM (浏览器对象模型)
  17. Expm 1_3 数组中逆序对个数问题
  18. [POJ3481]Double Queue
  19. Android通用框架设计与完整电商APP开发系列文章
  20. python 集合总结

热门文章

  1. DllImport的具体用法
  2. Caching Tutorial
  3. POJ 1922
  4. java基础知识回顾之---java StringBuffer,Stringbuilder与String的区别
  5. [主席树]SPOJ DQUERY
  6. POJ1248 Safecracker
  7. 【mongoDB中级篇②】索引与expain
  8. SSH公钥认证登录
  9. org.json和json-lib比较
  10. Maven是如何工作的