hihocoder 第一周 最长回文字串
题目1 : 最长回文子串
描述
小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。
这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”
小Ho奇怪的问道:“什么叫做最长回文子串呢?”
小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”
小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?
小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”
提示一
良久,小Ho仍然没有头绪,于是只能向小Hi求助。
小Hi清了清嗓子,缓缓说道:“让我从简单的说起吧,我给你一个字符串,你能不能告诉我它是不是一个回文串呢?”
小Ho回答道:“这个我当然可以啦!只要将这个字符串反过来,然后比较和原来的字符串是不是一样的不就行了?”
小Hi追问道:“也就是说你想要新建一个字符串咯?”
小Ho道:“那是当然,不然怎么比较呢?”
小Hi笑道:“但是你有没有注意到你在比较原来的字符串A和新字符串B的时候,A的第一个字符就是B的最后一个字符,而A的最后一个字符就是B的第一个字符,那么这样就比较了两次是不是浪费了效率呢?”
小Ho恍然道:“似乎是这样的!我知道了,我也不需要新建一个字符串了,我只需要比较A的第一个字符和最后一个字符是否相同,第二个字符和倒数第二个字符是否相同,以此类推,这样就只要比较字符串长度的一半次数就行了是不是?”
小Hi回答道:“没错!那你对于一个字符串,一一枚举它的子串,然后判断这个子串是不是回文子串,如果是的话就更新当前保存的最长的那一个,是不是就可以了?”
小Ho开心道:“是的!这个问题是不是就这么解决了?”
小Hi叹息道:“NONONO!你这最多也就拿个60分吧。”
小Ho遗憾的说道:“才及格啊,那我要怎么多拿点分呢?”
提示二
小Hi道:“不急不急,待我慢慢道来,你有没有想过之前的解法有没有什么问题?”
小Ho问道:“有什么问题?”
小Hi道:“你想想,如果一个字符串的[3, 7]这一段已经不是回文子串了,[2, 8]这一段还有可能是回文子串么?”
小Ho惊道:“好像不可能,那我之前不是有很多的计算都白费了,有没有什么办法来解决这个问题呢?我得好好想想!”言罢,小Ho沉思了起来。
良久,代表着成功的微笑出现来的小Ho的嘴边:“我知道了!我在枚举子串的时候换一种方式来进行枚举,不是枚举它的起止位置而是尝试枚举子串的中心位置,然后再从小到大依次枚举这个子串的长度,一旦发现已经不是一个回文串了就继续尝试下一个中心位置,这样,似乎就能够避免掉很多问题呢!”
小Hi赞许的点了点头,说道:“没错,这样的确会在一些情况下降低用于计算的时间呢,但是一个全是a的字符串,你这样的枚举方法似乎也没有多大用处呢?不过这样你也能拿个80分了哦!”
小Ho点了点头,说道:“没错,在最坏情况下,这种方法并没有比之前的方法好到哪里去,但是我的直觉告诉我肯定有更加高效的方法来进行计算呢,让我再好好想想吧!。”
提示三
小Ho这一想就是三天,小Hi也是看不下去了,决定来开导开导小Ho:“小Ho,你有没有想过,在之前的计算中,计算出以每一个位置为中心的最长回文子串的长度有没有什么用呢?”
小Ho答道:“我想想,如果以第5个字符为中心的最长回文子串的长度是5的话,这就告诉了我[3, 7]这一段是一个回文子串,所以呢?”
小Hi继续提示道:“假设这时候你想要计算以第6个字符为中心的最长回文子串的长度,你有没有什么已知的信息了?”
小Ho边想边说道:“唔,首先第6个字符和第4个字符是一样的,第7个字符和第3个字符是一样的,而第5个字符本身就肯定和第5个字符一样,那么如果[3, 5]这一段是回文子串的话,那么[5, 7]这一段肯定也是回文子串。也就是说,如果令f[i] 表示以第i个字符为中心的最长回文子串的长度,我们就会有f[i] >= f[i–2]?”
“不对,还要考虑到f[i – 1]的值,如果f[i – 1]太小就没有意义了,应该是f(i)≥min{f(i-2), f(i-1)-2}。”小Ho接着补充道。
“没错,但是还有一个问题,如果此时我告诉你f(5) = 1,但是f(4) = 7, f(2) = 3呢?”小Hi追问道。
小Ho想了想,回答道:“理论上来说,我可以通过这些信息知道f(6)>=3,但是由于f(5)=1所以我只能计算出来f(6)>=-1我知道了,我不应该是通过f(i – 1)来辅助计算,而是通过使得右边界(j + f(j) / 2)最大的那个j来辅助计算才是,所以公式将变成 f(i) ≥ min{f(2*j-i) , f(j) -2*(i-j)}这种形式了!”
小Hi继续问道:“那知道了这个公式之后,你打算怎么做呢?”
小Ho想也没想便道:“这简单,我只要在之前枚举中心位置那种方法的基础上,统计使得回文串右边界(j + f(j) / 2)最大的那个j,然后再计算每一个i的时候,都可以通过f(i)≥min{f(2*j-i), f(j)-2*(i-j)}这个公式来知道f(i)的一个最小值,这样即使是在我们所提到的那种最坏情况下,也可以节省掉很多不必要的计算呢~
提示四
一晃就是一周过去了,小Hi还是没有看到小Ho写的程序,于是决定上门去问问。到了小Ho家,小Hi惊讶的发现小Ho对着电脑屏幕,一脸郁闷的样子,于是他走上前问道:“小Ho小Ho,你怎么了啊?”
小Ho一点精神也没有的回答道:“就是上周的那个回文子串的程序啊,我写的时候发现我们当时考虑的解决方法只能处理长度为奇数的回文子串,长度为偶数的回文子串似乎要进行一点点细微的修改,但是这样修改过后就不能用我们最后写出的那个公式来互相帮助进行运算了,要进行很复杂的讨论,我就是一直在想有没有很优美的方法能来解决这个问题。”
小Hi惊讶道:“你就想这个想了一周么?我猜你一定是绕进了分类讨论的这个胡同里走不出来了,为什么不想想有没有别的解决方法呢?”
小Ho问道:“还有什么解决方法呀?”
小Hi答道:“既然长度为偶数的回文子串不好处理,我们为什么不去掉这些回文子串,只处理长度为奇数的回文子串呢?”
小Ho叹息道:“但是长度为偶数的回文子串也可以是答案啊!”
“除非……”小Hi插嘴道。
“除非什么?”小H问道。
“你将所有的长度为偶数的回文子串都变成长度为奇数的回文子串啊,你想想之所以是为偶数,那是因为没有一个中心字符,但是如果我们在原来字符串的基础上,在任意两个相邻的字符间都插入一个特殊字符,是不是无论是原来字符串中长度为奇数的回文子串还是长度为偶数的回文子串,在新的字符串中都有一个长度为奇数的回文子串与之进行对应呢?”
“哦!我了解了,这样我只需要对新的字符串按照我们之前的算法进行计算,统计出的最长回文子串将那些特殊字符去掉之后,就是原来字符串里的最长回文子串了。”小Ho开心的笑道,一连几天的郁闷也是一扫而空。
“但是要注意哦,我们希望得到的最长是原来字符串里的最长,而不是新字符串里的最长,毕竟特殊字符的个数会因为中心字符是不是特殊字符而有差别的哦。”小Hi提醒道。
“恩恩,这样我总能拿到满分了吧?”
“没错呢!”
样例输入
3
abababa
aaaabaa
acacdas
样例输出
7
5
3 分析:第一种先求一个串的所有字串,然后判断字串是否为回文串的复杂度为O(n^3);
第二种求以第i个字符为中心的回文串长度的方法,复杂度为O(n^2);
第三种:利用了回文串的特性,有名的manacher算法,时间复杂度为O(n),用一个数组记录每个以第i个字符为中心的回文串长度
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int N = ;
char a[N], b[N << ];//b数组保存的为a字符串处理后的字符串
int p[N << ]; int main(){
int t;//t为测试组数
scanf("%d", &t);
while(t--){
scanf("%s", a);//a为输入的字符串
int len = strlen(a);//len为输入字符串的长度
b[] = '$';
b[] = '#';
for(int i = ; i < len; i++){
b[(i << ) + ] = a[i];
b[(i << ) + ] = '#';
}
len = len * + ;
b[len] = '\0';
int maxId = , maxL = , id;//maxL表示最长回文字串长度
for(int i = ; i < len; i++){
if(maxId > i)
p[i] = min(p[ * id - i], maxId - i);
else p[i] = ;
while(b[i - p[i]] == b[i + p[i]])
p[i]++;
if(p[i] + i > maxId){
maxId = p[i] + i;
id = i;
}
if(p[i] > maxL)
maxL = p[i];
}
printf("%d\n", maxL - );
}
return ;
}
p[i]保存的不是以第i个字符为中心的回文串的长度。
hihocoder 第一周 最长回文字串的更多相关文章
- hihoCoder第一周---最长回文子串(1032)
其实这就是mancher算法的板子题,贴个代码好了. 思想请见我的另一篇博客: https://blog.csdn.net/qq_41090676/article/details/86768361 # ...
- POJ 3974 最长回文字串(manacher算法)
题意:给出一个字符串,求出最长回文字串. 思路:一开始我直接上了后缀数组DC3的解法,然后MLE了.看了DISCUSS发现还有一种计算回文字串更加优越的算法,就是manacher算法.就去学习了一下, ...
- 最长回文字串——manacher算法
时间复杂度:O(n) 参考:https://segmentfault.com/a/1190000003914228 1.问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字 ...
- 求字符串的最长回文字串 O(n)
昨天参加了某公司的校园招聘的笔试题,做得惨不忍睹,其中就有这么一道算法设计题:求一个字符串的最长回文字串.我在ACM校队选拔赛上遇到过这道题,当时用的后缀数组AC的,但是模板忘了没写出代码来. 回头我 ...
- HihoCoder第一周与POJ3974:最长回文字串
这个题目是hihoCoder第一周的题目,自己打算从第一周开始做起,不知道能追上多少,更不知道这一篇写完,下一篇会是什么时候... 题意很简单. 输入: abababa aaaabaa acacdas ...
- Hdu 3068 最长回文字串Manacher算法
题目链接 最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- 最长回文字串 (The longest palindrome substring)
这两天去学了一下,觉得下面那篇文章写的很好,有例子,比较容易懂,所以转一下. 以下内容来自:hihoCoder: 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互 ...
- hiho一下 第一周 最长回文子串
时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这 ...
- 【hiho一下】第一周 最长回文子串
题目1:最长回文子串 题目原文:http://hihocoder.com/contest/hiho1/problem/1 [题目解读] 题目与 POJ 3974 palindrome 基本同样.求解最 ...
随机推荐
- WPF——文本随滚动条改变而改变
一.造一个窗体,拖进一个文本框TextBox和滚动条Slider 二.让文本框的内容随滚动条的滚动而改变,即文本框绑定到滚动条上 三.实现效果
- Linux kernel ‘xfs_attrlist_by_handle()’函数缓冲区溢出漏洞
漏洞名称: Linux kernel ‘xfs_attrlist_by_handle()’函数缓冲区溢出漏洞 CNNVD编号: CNNVD-201311-392 发布时间: 2013-11-29 更新 ...
- VMWare12 安装 OSX 10.10
推荐电脑配置 1:Inter I5及以上 (A卡请自行百度大神解决方案) 必须开启CPU虚拟化:开机进入 BIOS ---> Intel Virtualization Technology--- ...
- RMAN综合学习之备份
rman是最经济实惠的oracle备份工具,在这里做一个rman的整体学习. 文章中大多是rman命令的语法,还是最好做做实验,以便印象深刻,因为大多数数据库的备份就是按时跑脚本,恢复也不是经常能遇到 ...
- 嵌入式开发软件环境:uboot、kernel、rootfs、data布局分析
uboot+linux的整体方案 开发板的datasheet中都有详细的地址空间的划分,其中比较重要的两块是:DDR地址空间和Flash地址空间.DDR空间是系统和应用的运行空间,一般由linux系统 ...
- GIS数据格式:Shapefile
转自:http://lab.osgeo.cn/2449.html Shapefile是ESRI提出的数据格式,随着ArcView GIS 3.x发布,属于简单要素类.Shapefile由于其数据结构简 ...
- 谈谈分布式事务之三: System.Transactions事务详解[上篇]
在.NET 1.x中,我们基本是通过ADO.NET实现对不同数据库访问的事务..NET 2.0为了带来了全新的事务编程模式,由于所有事务组件或者类型均定义在System.Transactions程序集 ...
- 转载--C++ STL
转自:http://wenku.baidu.com/view/15d18b4533687e21af45a9a4.html 1.C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vec ...
- OpenGL立方体在世界坐标系中_缩放_旋转_平移_顶点片源着色器_光照作用_棋盘纹理贴图
读取bmp等图片格式中的像素还有难度,就先用这个棋盘图象素来弄了 代码打错一个就一直First-chance exception ,貌似还有一个要用q或者Q才能成功退出,不知道缺少哪句,我用窗口红叉退 ...
- 重装mysql步骤
, 卸载MySQL 2, 删除目录 C:\Documents and Settings\All Users\Application Data\MySQL (这个真的有,原先没注意到,删掉!) 如果没有 ...