【转载】最长回文字符串(manacher算法)
原文转载自:http://blog.csdn.net/lsjseu/article/details/9990539
偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙。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-i]表示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算法)的更多相关文章
- 最长回文字符串(manacher算法)
偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述: 回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...
- 第5题 查找字符串中的最长回文字符串---Manacher算法
转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...
- 九度OJ 1528 最长回文子串 -- Manacher算法
题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...
- lintcode最长回文子串(Manacher算法)
题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...
- 最长回文子串—Manacher 算法 及 python实现
最长回文子串问题:给定一个字符串,求它的最长回文子串长度.如果一个字符串正着读和反着读是一样的,那它就是回文串. 给定一个字符串,求它最长的回文子串长度,例如输入字符串'35534321',它的最 ...
- hihocoder #1032 : 最长回文子串 Manacher算法
题目链接: https://hihocoder.com/problemset/problem/1032?sid=868170 最长回文子串 时间限制:1000ms内存限制:64MB 问题描述 小Hi和 ...
- 5. Longest Palindromic Substring(最长回文子串 manacher 算法/ DP动态规划)
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]
传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...
- HDU 3068:最长回文(Manacher算法)
http://acm.hdu.edu.cn/showproblem.php?pid=3068 最长回文 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的 ...
随机推荐
- 微信小程序里使用 Redux 状态管理
微信小程序里使用 Redux 状态管理 前言 前阵子一直在做小程序开发,采用的是官方给的框架 wepy , 如果还不了解的同学可以去他的官网查阅相关资料学习:不得不说的是,这个框架确相比于传统小程序开 ...
- ZIP文件流压缩和解压
前面写了一篇文章 "ZIP文件压缩和解压", 介绍了" SharpZipLib.Zip " 的使用, 最近的项目中,在使用的过程中, 遇到一些问题. 比如, 现 ...
- 一次ddos攻击
公司lvs的vip受到攻击,表现现象为: 1)vip所有服务器没有什么连接,大量的无效connection 2)网卡流量很大 停用vip,流量下降,临时解决攻击问题.但是这只是治标不治本,如果攻击方变 ...
- 数据结构(C#):图的最短路径问题、(Dijkstra算法)
今天曾洋老师教了有关于图的最短路径问题,现在对例子进行一个自己的理解和整理: 题目: 要求:变成计算出给出结点V1到结点V8的最短路径 答: 首先呢,我会先通过图先把从V1到V8的各种路径全部计算下来 ...
- Altium_Designer-怎么将“原理图的更改”更新到“pcb图”?
打开原理图,直击菜单栏>>Design,选择第一项,>>Update PCB Document...在弹出的对话框里面选择执行更改即可将原理图更新到工程下面对应的PCB.也可以 ...
- AD的命名规则 AD常用产品型号命名规则
AD的命名规则 AD常用产品型号命名规则 DSP信号处理器 放大器工业用器件通信 电源管理 移动通信 视频/图像处理器等 模拟A/D D/A 转换器 传感器 模拟器件 A ...
- SAP成都C4C小李探花:浅谈Fiori Design Guidelines
Jerry: 我和周帅认识不久,自去年7月SAP成都研究院Cloud for Customer(以下简称为C4C)开发团队组建至今,根据这段时间和周帅愉快的合作经历,我觉得如果把周帅比作我读过的小说里 ...
- 2019.03.16 ZJOI2019模拟赛 解题报告
得分: \(100+27+20=147\)(\(T1\)巨水,\(T2,T3\)只能写暴力分) \(T1\):深邃 比较套路的一眼题,显然是一个二分+贪心,感觉就是\(NOIP2018Day1T3\) ...
- D. Bicycle Race_几何
D. Bicycle Race time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- 20145238-荆玉茗 《Java程序设计》第二周学习总结
20145238 <Java程序设计>第2周学习总结 教材学习内容总结 关于一些格式方面的问题: 1.关键字:在定义java文件名的时候要避免这些关键字的出现,因为他们在java程序语言中 ...