有种简单的方法,数组从左到右扫一遍,每次以当前的点为中心,只要左右相等就往左右走,这算出来的回文字符串是奇数长度的

还有偶数长度的回文字符串就是以当前扫到的点和它左边的点作为中心,然后往左右扫

这是O(n^2)的复杂度,这道题过还是没有问题的

这里我主要练习的是另外的利用后缀数组加RMQ算法来解决这个问题

大致思想跟上面一致

首先将字符串反转贴在原字符串末尾,将字符通过ASCII码转化为字符,之间用一个1分开,最后贴一个0

然后得到它的后缀数组以及height[]数组

那么找回文字符也是扫一遍,每次以当前点作为偶数情况和奇数情况的中心

然后找到后来倒置的字符串对应字符的位置,这样二者的前缀一个是往前走的,一个是往后走的,正好贴一块就是回文的

但是这个查询为加快速度,就要用RMQ算法,求得区间内height数组的最小值

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
#define MAXN 2010
int sa[MAXN] , height[MAXN] , _rank[MAXN];
int wa[MAXN] , wb[MAXN] , wsf[MAXN] , wv[MAXN] , r[MAXN];
int dp[MAXN][];
char str[MAXN]; int cmp(int *r , int a , int b , int l)
{
return r[a]==r[b] && r[a+l]==r[b+l];
} void getSa(int *r , int *sa , int n , int m)
{
int i,j,p;
int *x=wa , *y=wb , *t; for(i= ; i<m ; i++) wsf[i]=;
for(i= ; i<n ; i++) wsf[x[i]=r[i]]++;
for(i= ; i<m ; i++) wsf[i]+=wsf[i-];
for(i=n- ; i>= ; i--) sa[--wsf[x[i]]]=i; p=;
for(j= ; 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++) wsf[i]=;
for(i= ; i<n ; i++) wsf[wv[i]]++;
for(i= ; i<m ; i++) wsf[i]+=wsf[i-];
for(i=n- ; i>= ; i--)sa[--wsf[wv[i]]]=y[i]; t=x , x=y , y=t;
x[sa[]]=;
for(i=,p=;i<n;i++)
x[sa[i]] = cmp(y , sa[i-] , sa[i] , j)?p-:p++;
}
return ;
} void callHeight(int *r , int *sa , int n)
{
int i,j,k=;
for(i= ; i<=n ; i++) _rank[sa[i]]=i;
// for(i=0 ; i<n ; i++) cout<<"_rank: "<<_rank[i]<<endl;
for(i= ; i<n ; height[_rank[i++]]=k)
for(k?k--: , j=sa[_rank[i]-]; r[i+k]==r[j+k] ; k++);
return ;
} void ST(int n)
{
//将height数组进行RMQ询问
memset(dp , 0x3f , sizeof(dp));
for(int i= ; i<=n ; i++) dp[i][]=height[i];
for(int j= ; (<<(j-))<n+ ; j++)
for(int i= ; i<=n ; i++)
dp[i][j] = min(dp[i][j-] , dp[i+(<<(j-))][j-]); return;
} int get_min(int s , int t)
{
int len = t-s+;
int l=floor(log(len*1.0)/log(2.0));
return min(dp[s][l] , dp[t-(<<l)+][l]);
} void solve(int n , int &left , int &right)
{
int ans = ;
//奇数情况
for(int i= ; i<n ; i++){
int j=*n-i;
int s=min(_rank[i] , _rank[j]);
int t=max(_rank[i] , _rank[j]);
int tmp = get_min(s+ , t);
if(ans<tmp*-){
ans = tmp*-;
left=i-tmp+ , right=i+tmp-;
}
}
//偶数情况
for(int i= ; i<n ; i++){
int j = *n-i+;
int s=min(_rank[i] , _rank[j]);
int t=max(_rank[i] , _rank[j]);
int tmp = get_min(s+ , t);
if(ans<tmp*){
ans = tmp*;
left=i-tmp , right=i+tmp-;
}
}
return;
} int main()
{
// freopen("a.in" , "r" , stdin);
while(~scanf("%s" , str))
{
int len = strlen(str);
r[len]=;
for(int i= ; i<len ; i++){
r[i] = (int)str[i];
r[*len-i] = r[i];
}
r[*len+]=; getSa(r , sa , *len+ , );
callHeight(r , sa , *len+);
//建立RMQ查询数组
ST(*len+);
int left= , right=;
solve(len , left , right);
str[right+]='\0';
printf("%s\n" , str+left);
}
return ;
}

URAL 1297 求最长回文字符串的更多相关文章

  1. URAL 1297 Palindrome 最长回文子串

    POJ上的,ZOJ上的OJ的最长回文子串数据量太大,用后缀数组的方法非常吃力,所以只能挑个数据量小点的试下,真要做可能还是得用manacher.贴一下代码 两个小错,一个是没弄懂string类的sub ...

  2. 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297

    1297. Palindrome Time Limit: 1.0 secondMemory Limit: 16 MB The “U.S. Robots” HQ has just received a ...

  3. Manacher算法 - 求最长回文串的利器

    求最长回文串的利器 - Manacher算法 Manacher主要是用来求某个字符串的最长回文子串. 不要被manacher这个名字吓倒了,其实manacher算法很简单,也很容易理解,程序短,时间复 ...

  4. 最长回文字符串(manacher算法)

    偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述:      回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...

  5. PAT甲题题解-1040. Longest Symmetric String (25)-求最长回文子串

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789177.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  6. 【转载】最长回文字符串(manacher算法)

    原文转载自:http://blog.csdn.net/lsjseu/article/details/9990539 偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid ...

  7. Manacher算法:求解最长回文字符串,时间复杂度为O(N)

    原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...

  8. Manacher模板( 线性求最长回文子串 )

    模板 #include<stdio.h> #include<string.h> #include<algorithm> #include<map> us ...

  9. [hdu3068 最长回文]Manacher算法,O(N)求最长回文子串

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意:求一个字符串的最长回文子串 思路: 枚举子串的两个端点,根据回文串的定义来判断其是否是回文 ...

随机推荐

  1. 题解报告:hdu 2084 数塔(递推dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2084 Problem Description 在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这 ...

  2. java.lang.UnsatisfiedLinkError: E:\TomcatV7_iot\bin\tcnative-1.dll: Can't load AMD 64-bit .dll on a IA 32-bit platform

    启动64位Tomcatv7时报如下错误: java.lang.UnsatisfiedLinkError: E:\TomcatV7_iot\bin\tcnative-.dll: Can't load A ...

  3. Environment中有大量访问目录的函数

    public class Environment { /** * Return root of the "system" partition holding the core An ...

  4. Android开发学习——android数据存储

    Android的存储 Android中的数据存储方式及其存储位置 SharedPrefrence存储 1). 位置           /data/data/packageName/shared_pr ...

  5. AJPFX:学习JAVA程序员两个必会的冒泡和选择排序

    * 数组排序(冒泡排序)* * 冒泡排序: 相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处* * 选择排序 : 从0索引开始,依次和后面元素比较,小的往前放,第一次完毕,最小值出现 ...

  6. 【Java】包装类型

    Java中的基本类型功能简单,不具备对象的特性,为了使基本类型具备对象的特性,所以出现了包装类,就可以像操作对象一样操作基本类型数据. 一.基本类型对应的包装类 基本类型                ...

  7. skeljs框架关键点使用

    global  全局 style.css    containers: 1400px;容器宽度 xlarge  超大屏(media: max-width:1680px) style-xlarge.cs ...

  8. 遮罩 HUD 指示器 蒙板 弹窗

    遮罩 HUD 指示器 蒙板 弹窗 UIAlertView的使用<代理方法处理按钮点击> UIAlertView *alertView = [[UIAlertView alloc] init ...

  9. jquery中ajax使用error调试错误

    error:function (XMLHttpRequest, textStatus, errorThrown) { } XMLHttpRequest.readyState状态码  0:未初始化还没有 ...

  10. php+nginx 限制上传文件大小

    问题:在后台上传8M大小的图片,上传不成功 nginx返回413,如下图所示: 分析:nginx配置文件或者php中,可上传的大小设置太小了 解决办法------检查nginx和php的配置文件里面的 ...