回文串包括奇数长的和偶数长的,一般求的时候都要分情况讨论,这个算法做了个简单的处理把奇偶情况统一了。算法的基本思路是这样的,把原串每个字符中间用一个串中没出现过的字符分隔开来(统一奇偶),用一个数组p[ i ]记录以 str[ i ] 为中间字符的回文串向右能匹配的长度。先看个例子

原串:       w  a   a   b   w   s   w   f   d

新串(str):  #   w  #   a   #   a   #   b  #   w   #   s    #   w    #     f    #    d     #

0   1   2   3   4    5   6   7   8   9  10  11 12  13  14   15  16   17   18

p数组:     1   2   1   2   3    2   1   2   1   2   1    4   1    2    1     2    1    2    1

由p数组的性质,新串中以str[i]为中间字符的回文串的长度为p[i]-1(可以对照p[11]这个位置,p[i]-1本身表示对称半径,但是实际上去掉#以后,p[i]-1就是回文串长度),以#为中间字符的就是长度为偶数的,以非#号为中间字符的就是长度为奇数的,那么怎么求p[ ]数组呢?

从左到右计算(0~str.length),也就是计算p[i]时,p[0.....i-1] 都已经计算出来了,并且用一个变量mx记录当前检测出的回文串的右侧最大位置 max{ k+p[ k ] } (k=0.....i-1),用id记录取最大值时的k。


上面的这个截图是很多人都用过的,需要注意的是, 两张图分别表示了当前点i<mx时的两种情况:

1) 当前点i关于id的对称点j, 以j为中心的回文串的左边界不小于id-p[id],根据回文串的对称性, 这就意味着i的回文串长度是跟j是一样的, 所以有p[i] = p[j] = p[2*id-i];

2) 如果以j为中心的回文串的左边界小于id-p[id],则只能确保p[i]>=mx-i, 至于p[i]的值具体为多少,还需要检测mx后面的位置才能确定出来。

所以就有了下面的这个关键代码,理解了这部分,整个算法就好理解了。

if( mx > i )

p[i] = MIN( p[*id-i], mx-i );

完整代码如下:

 #include<iostream>
#include<string>
#include<stdlib.h>
using namespace std; char cArray[];
int p[]; int manacher(int length)
{
int mx = ;
int id = ;
int maxLength = ; for(int i=; i<length; ++i)
{
if(mx>i)
{
p[i] = min(p[*id-i], mx-i);
}
else
{
p[i] = ;
} while( (i-p[i]+)>= && (i+p[i]-)<length && cArray[i-p[i]+]==cArray[i+p[i]-] )
{
p[i] = p[i] + ;
} p[i]--; if(i+p[i]- > mx)
{
mx = i+p[i]-;
id = i;
} if(maxLength < p[i]-)
{
maxLength = p[i]-;
}
} return maxLength;
} int main()
{
//string input = "waabwswfd";
string input = "wawbbbwasaw";
int k = ;
for(int i=; i<input.size(); ++i)
{
cArray[k++] = '#';
cArray[k++] = input.at(i);
}
cArray[k++] = '#';
int ans = manacher(k);
cout << ans << endl;
}

简化以后的代码

#include<iostream>
#include<string>
#include<cstdlib>
#include<algorithm> using namespace std; char cArray[];
int p[]; int manacher(int length)
{
int mx = ;
int id = ;
int maxLength = ; for (int i = ; i<length; ++i)
{
if (mx>i)
{
p[i] = min(p[ * id - i], mx - i);
}
else
{
p[i] = ;
} while ((i - p[i]) >= && (i + p[i])<length && cArray[i - p[i]] == cArray[i + p[i]])
{
p[i] = p[i] + ;
} p[i]--; if (i + p[i] > mx)
{
mx = i + p[i];
id = i;
} if (maxLength < p[i])
{
maxLength = p[i];
}
} return maxLength;
} int main()
{
//string input = "waabwswfd";
string input = "wawbbbwasaw";
int k = ;
for (int i = ; i<input.size(); ++i)
{
cArray[k++] = '#';
cArray[k++] = input.at(i);
}
cArray[k++] = '#';
int ans = manacher(k);
cout << ans << endl;
}

求最长回文子串——Manacher算法的更多相关文章

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

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

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

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

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

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

  4. 51nod1089 最长回文子串 manacher算法

    0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字符串正着读和反着读是一样的,那它就是回文串.下面是一些回文串的实例: 12321 a aba abba aaaa ...

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

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

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

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

  7. HiHo 1032 最长回文子串 (Manacher算法求解)

    /** * 求解最长回文字串,Manacher算法o(n)求解最长回文子串问题 **/ #include<cstdio> #include<cstdlib> #include& ...

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

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

  9. 最长回文子串Manacher算法模板

    Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 首先,在字符串s中,用rad[i]表示第i个字符 ...

随机推荐

  1. 设置只为View加一条边框,子视图大小超出父视图大小,边框在子视图下边显示

    #import "ViewController.h" @interface ViewController () @property (strong,nonatomic) UIVie ...

  2. 【转载】.NET(C#): Task.Unwrap扩展方法和async Lambda

    .NET(C#): Task.Unwrap扩展方法和async Lambda 目录 Task.Unwrap基本使用 Task.Factory.StartNew和Task.Run的Unwrap操作 使用 ...

  3. CentOS搭建Httpd Pyhton3 Django环境

    系统环境 centos-6-x86 系统自带httpd 编译安装Python3 pip3 参考 http://www.cnblogs.com/vawter/p/6254170.html 编译安装wsg ...

  4. linux ssh免密码登录设置

    ssh-keygen -t rsa 全部回车 生成密钥默认放在了/root/.shh中 打开它 cd /root/.ssh cp id_rsa.pub authorized_keys 免密码登录 现在 ...

  5. php文件遍历类:FileBianli.class.php

    <?php class FileBianli{ private $dirname; private $dirsize=0; private $totalsize=0;//当前目录大小 funct ...

  6. HDU-4405 Aeroplane chess(概率DP求期望)

    题目大意:一个跳棋游戏,每置一次骰子前进相应的步数.但是有的点可以不用置骰子直接前进,求置骰子次数的平均值. 题目分析:状态很容易定义:dp(i)表示在第 i 个点出发需要置骰子的次数平均值.则状态转 ...

  7. appium简明教程(6)——启动appium及android模拟器

    一般情况下,我们都从命令行启动appium. windows下,dos命令窗口输入 appium 如果该命令报错,那么请重装appium npm install -g appium 如果安装出错,请自 ...

  8. *** 安全沙箱冲突 *** 到 127.0.0.1:9999 的连接已停止 - 不允许从 file:///E:/flash/Flash/Vod/tag/Letvcloud__MainVodNew/bin-debug/Player.swf 进行连接

    http://bbs.9ria.com/thread-69309-1-1.html C:\Windows\System32\Macromed\Flash\NPSWF64_21_0_0_242.dll ...

  9. 数据库事务隔离级ORACLE数据库事务隔离级别介绍

    本文系转载,原文地址:http://singo107.iteye.com/blog/1175084 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committ ...

  10. A Flock Of Tasty Sources On How To Start Learning High Scalability

    This is a guest repost by Leandro Moreira. When we usually are interested about scalability we look ...