URAL 1297 求最长回文字符串
有种简单的方法,数组从左到右扫一遍,每次以当前的点为中心,只要左右相等就往左右走,这算出来的回文字符串是奇数长度的
还有偶数长度的回文字符串就是以当前扫到的点和它左边的点作为中心,然后往左右扫
这是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 求最长回文字符串的更多相关文章
- URAL 1297 Palindrome 最长回文子串
POJ上的,ZOJ上的OJ的最长回文子串数据量太大,用后缀数组的方法非常吃力,所以只能挑个数据量小点的试下,真要做可能还是得用manacher.贴一下代码 两个小错,一个是没弄懂string类的sub ...
- 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297
1297. Palindrome Time Limit: 1.0 secondMemory Limit: 16 MB The “U.S. Robots” HQ has just received a ...
- Manacher算法 - 求最长回文串的利器
求最长回文串的利器 - Manacher算法 Manacher主要是用来求某个字符串的最长回文子串. 不要被manacher这个名字吓倒了,其实manacher算法很简单,也很容易理解,程序短,时间复 ...
- 最长回文字符串(manacher算法)
偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述: 回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...
- PAT甲题题解-1040. Longest Symmetric String (25)-求最长回文子串
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789177.html特别不喜欢那些随便转载别人的原创文章又不给 ...
- 【转载】最长回文字符串(manacher算法)
原文转载自:http://blog.csdn.net/lsjseu/article/details/9990539 偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid ...
- Manacher算法:求解最长回文字符串,时间复杂度为O(N)
原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...
- Manacher模板( 线性求最长回文子串 )
模板 #include<stdio.h> #include<string.h> #include<algorithm> #include<map> us ...
- [hdu3068 最长回文]Manacher算法,O(N)求最长回文子串
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意:求一个字符串的最长回文子串 思路: 枚举子串的两个端点,根据回文串的定义来判断其是否是回文 ...
随机推荐
- 贪心 UVALive 6834 Shopping
题目传送门 /* 题意:有n个商店排成一条直线,有一些商店有先后顺序,问从0出发走到n+1最少的步数 贪心:对于区间被覆盖的点只进行一次计算,还有那些要往回走的区间步数*2,再加上原来最少要走n+1步 ...
- 转-解决Mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost'问题
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) Red Hat Enterpr ...
- ORA-28002错误原因及解决办法
在oracle database 11g中,默认在default概要文件中设置了“PASSWORD_LIFE_TIME=180天”所导致.密码过期后,业务进程连接数据库异常,影响业务使用.数据库密码过 ...
- hdu3433A Task Process( 二分dp)
链接 二分时间,在时间内dp[i][j]表示截止到第i个人已经做了j个A最多还能做多少个B #include <iostream> #include<cstdio> #incl ...
- Java 线程 —— Wait (等待)和 Notify(唤醒)
Wait (等待)和 Notify(唤醒) 这里讲了一个Wait (等待)和 Notfity(唤醒),下面这个实例(工厂,商店,消费者) 额,然后,你就知道了,需要写三个类:工厂类,Shop类,消费者 ...
- hihocoder offer收割编程练习赛12 C 矩形分割
思路: 模拟,深搜. 实现: #include <iostream> #include <cstdio> #include <string> using names ...
- call、apply/bind的区别和用法(简单粗暴的解释)
var obj1={ name:"bob", age:20 } var obj2={ name:"coco", age:22 } function getAge ...
- Zookeeper系列(一)
一.ZooKeeper的背景 1.1 认识ZooKeeper ZooKeeper---译名为“动物园管理员”.动物园里当然有好多的动物,游客可以根据动物园提供的向导图到不同的场馆观赏各种类型的动物,而 ...
- laravel学习:容器绑定与解析
1.在服务容器中注册类(bind) $this->app->bind('sender','MailSender');//$this->app成为服务容器. 2.从服务容器生成类( ...
- pringBoot Controller接收参数的几种常用方式
第一类:请求路径参数1.@PathVariable 获取路径参数.即url/{id}这种形式.2.@RequestParam 获取查询参数.即url?name=这种形式例子 GEThttp://loc ...