偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙。Stupid。

题目描述:
     回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。  
     回文子串,顾名思义,即字符串中满足回文性质的子串。   
     给出一个只由小写英文字符a,b,c...x,y,z组成的字符串,请输出其中最长的回文子串的长度。
输入:
     输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c...x,y,z组成的字符串,字符串的长度不大于200000。
输出:
     对于每组测试用例,输出一个整数,表示该组测试用例的字符串中所包含的的最长回文子串的长度。
样例输入:
abab
bbbb
abba
样例输出:
3
4
4

思路:

回文串包括奇数长的和偶数长的,一般求的时候都要分情况讨论,这个算法做了个简单的处理把奇偶情况统一了。原来是奇数长度还是奇数长度,偶数长度还是偶数长度。

算法的基本思路是这样的,把原串每个字符中间用一个串中没出现过的字符分隔#开来(统一奇偶),同时为了防止越界,在字符串的首部也加入一个特殊符$,但是与分隔符不同。同时字符串的末尾也加入'\0'.

算法的核心:用辅助数组p记录以每个字符为核心的最长回文字符串半径。也就是p[i]记录了以str[i]为中心的最长回文字符串半径。p[i]最小为1,此时回文字符串就是字符串本身。

先看个例子:

原串:        w aa bwsw f d
      新串:     $ # w# a # a # b# w # s # w # f # d #
辅助数组P:    1  2 1 2 3 2 1 2 1 2 1 4 1 2 1 2 1 2 1

首先看代码(借助http://blog.csdn.net/thyftguhfyguj/article/details/9531149):

#include <stdio.h>
#include <iostream>
using namespace std; char s[200002];
char str[400010];
int p[400010]; int min(int a,int b){
return a < b ? a : b;
} int pre(){
int i,j = 0;
str[j++] = '$';//加入字符串首部的字符串
for(i = 0;s[i];i++){
str[j++] = '#'; //分隔符
str[j++] = s[i];
}
str[j++] = '#';
str[j] = '\0'; //尾部加'\0'
cout<<str<<endl;
return j;
} void manacher(int n){
int mx = 0,id,i;
p[0] = 0;
for(i = 1;i < n;i++){
if(mx > i) //在这个之类可以借助前面算的一部分
p[i] = min(mx - i,p[2 * id - i]); //p[2*id-1]表示j处的回文长度
else //如果i大于mx,则必须重新自己算
p[i] = 1;
while(str[i - p[i]] == str[i + p[i]]) //算出回文字符串的半径
p[i]++;
if(p[i] + i > mx){ //记录目前回文字符串扩展最长的id
mx = p[i] + i;
id = i;
}
}
} int main(int argc, char const *argv[]){ while(scanf("%s",s) != EOF){
int n = pre();
manacher(n);
int ans = 0,i;
for(i = 1;i < n;i++)
if(p[i] > ans)
ans = p[i];
printf("%d\n",ans - 1);
}
return 0;
}

上面的程序说明:pre()函数对给定字符串进行预处理,也就是加分隔符。

上面几个变量说明:id记录具有遍历过程中最长半径的回文字符串中心字符串。mx记录了具有最长回文字符串的右边界。看下面这个图(注意,j为i关于id对称的点,j = 2*id - i):

但是p[i] = p[j]是没有错的,但是这里有个问题,就是i的一部分超出阴影部分,这就不对了。请看下图(为了看得更清楚,下面子串用细条纹表示):

此时,根据对称型只能得出p[i]和p[j]红色阴影部分是相等的,这就为什么有取最小值这个操作:

if(mx > i)  //在这个之类可以借助前面算的一部分
p[i] = min(mx - i,p[2 * id - i]);

下面代码就很容易看懂了。

最后遍历一遍p数组,找出最大的p[i]-1就是所求的最长回文字符串长度,下面证明一下:

(1)因为p[i]记录插入分隔符之后的回文字符串半径,注意插入分隔符之后的字符串中的回文字符串肯定是奇数长度,所以以i为中心的回文字符串长度为2*p[i]-1。

例如:bb=>#b#b#

bab=>#b#a#a#b#

(2)注意上面两个例子的关系。#b#b#减去一个#号的长度就是原来的2倍。即((2*p[i]-1)-1)/2 = p(i)-1,得证。

算法的有效比较次数为MaxId 次,所以说这个算法的时间复杂度为O(n)。

最长回文字符串(manacher算法)的更多相关文章

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

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

  2. 第5题 查找字符串中的最长回文字符串---Manacher算法

    转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...

  3. 九度OJ 1528 最长回文子串 -- Manacher算法

    题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...

  4. lintcode最长回文子串(Manacher算法)

    题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...

  5. 最长回文子串—Manacher 算法 及 python实现

    最长回文子串问题:给定一个字符串,求它的最长回文子串长度.如果一个字符串正着读和反着读是一样的,那它就是回文串.   给定一个字符串,求它最长的回文子串长度,例如输入字符串'35534321',它的最 ...

  6. hihocoder #1032 : 最长回文子串 Manacher算法

    题目链接: https://hihocoder.com/problemset/problem/1032?sid=868170 最长回文子串 时间限制:1000ms内存限制:64MB 问题描述 小Hi和 ...

  7. 5. Longest Palindromic Substring(最长回文子串 manacher 算法/ DP动态规划)

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  8. hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]

    传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...

  9. HDU 3068:最长回文(Manacher算法)

    http://acm.hdu.edu.cn/showproblem.php?pid=3068 最长回文 Problem Description   给出一个只由小写英文字符a,b,c...y,z组成的 ...

随机推荐

  1. Eclipse 运行ant build.xml

    在命令行cmd运行mvn clean install,ant compiler,提示上述信息,是因为 maven的这个插件要求jdk1.6,但是本地电脑环境变量jdk版本为1.7.将JAVA_HOME ...

  2. PHP Socket编程起步

    让我们以一个简单的例子开始---一个接收输入字符串,处理并返回这个字符串到客户端的TCP服务.下面是相应的代码: PHP 代码: ) or die("Could not read input ...

  3. Windows系统创建硬链接文件

    源文件夹:E:\深海 创建新硬链接文件夹:D:\微云同步盘\719179409\4-工作资料\深海   打开命令提示符(管理员) 敲入以下命令:   创建成功后,进入目录 D:\微云同步盘\71917 ...

  4. iOS8中添加的extensions总结(二)——分享扩展

    分享扩展 注:此教程来源于http://www.raywenderlich.com的<iOS8 by Tutorials> 1.准备 这次例子来源于国外的图片分享网站Imgur.com 首 ...

  5. XML DOM 总结一

        对这个基本概念我不介绍太多,无非就是一定格式的文本而已,我现在侧重于如何使用它.      首先看看.NET对它的支持.      首先看看这个类图:            所有的都是基于Xm ...

  6. 【转】Qt之模型/视图

    [本文转自]http://blog.sina.com.cn/s/blog_a6fb6cc90101hh20.html   作者: 一去丶二三里 关于Qt中MVC的介绍与使用,助手中有一节模型/视图编程 ...

  7. 【转】常用背景色RGB数值

    [转自]http://blog.sina.com.cn/s/blog_8fc890a201013z8h.html

  8. Mysql中存储方式的区别

    MySQL的表属性有:MyISAM 和 InnoDB 2种存储方式: MyISAM 不支持事务回滚 InnoDB 支持事务回滚 可以用 show create table tablename 命令看表 ...

  9. 安装SQL Server 那些事儿

    SQL版本: Microsoft SQL Server2008 R2 RTM - Express with Advanced Services 错误描述: System.Configuration.C ...

  10. 网络请求时 返回 App Transport Security has blocked a cleartext HTTP

    如上图,是因为 Xcode7 没有对 plist 进行 http 请求的配置  所致 这时需要  加上上面的plist的红框中 的内容  并且 设置 为 yes  如下图