马拉车(manacher)算法——最长回文(hdu3068)
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3068
题目描述:
Problem Description
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
Output
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input
aaaa
abab
Sample Output
4
3
解题思路:
计算字符串的最长回文字串最简单的算法就是枚举该字符串的每一个子串,并且判断这个子串是否为回文串,这个算法的时间复杂度为O(n^3)的,显然无法令人满意,稍微优化的一个算法是枚举回文串的中点,这里要分为两种情况,一种是回文串长度是奇数的情况,另一种是回文串长度是偶数的情况,枚举中点再判断是否是回文串,这样能把算法的时间复杂度降为O(n^2),但是当n比较大的时候仍然无法令人满意,Manacher算法可以在线性时间复杂度内求出一个字符串的最长回文字串,达到了理论上的下界。
我们先看最长回文串的几个关键点问题:
一、显然,当我们找到中心点时,利用回文串的特性进行双向遍历是最好的解决办法,但是由于奇偶性的问题导致我们无法准确的定位中心点
二、遍历所有回文串显然有些不必要的废操作,因为必然存在许多子回文串在较大的回文串内部,比如说abcdcba,他就包含了bcdcba……所以我们考虑的就是如何把这些过滤掉。
马拉车Manacher算法就很巧妙的解决了这两个问题:
将长度为奇数的回文串和长度为偶数的回文串一起考虑,具体做法是,在原字符串的每个相邻两个字符中间插入一个分隔符,同时在首尾也要添加一个分隔符,分隔符的要求是不在原串中出现,比如说abcdcba 就变成了#a#b#c#d#c#b#a#,#也可以换成其他的,只要原串中不涉及到的字符即可。
如果变化后,回文串一定会是一个奇数,因为#的长度是原串长度+1 即新串总长度为2*原串长度+1
解决完奇偶性问题之后,接着用一个辅助数组Len[i]表示以字符T[i]为中心到边缘的长度,也就是以T[i]为中心点的回文串总长度/2+1
举两个例子:
T=#a#b#c#d#c#b#a#,那么Len即121212171212121
T=#a#a#a#b#a# ,那么Len即12343214121
所以我们要做的事,就是求最大的Len[i]即可
有了Len数组,我们就很容易判断出当前遍历的情况,设p_r为之前计算中回文串的最右端点,并且设取得这个最大值的中心点位置为po
对于当前点i,如果pr点大于i点,那么说明i点在po为中心这个最大回文串内部,我们设与其对称的一个点j,即从i点到po 和从po点到i是对称的。
那么我们可以认为:
以点j作为中心点的回文串(len[j])并且满足其在po回文串内部的长度(mx-i)对于i点来说 一样是对称的。
如果i点大于p_r,即之前并没有遍历过,那么肯定要从头开始匹配了。所以我们现在基本可以知道:对于字符串中的每一个位置,只进行一次匹配,所以Manacher算法的总体时间复杂度为O(n),其中n为字符串的长度,当前,其长度是原始字符串长度的2倍。另外,为了避免匹配时数组越界,我们在字符串两边加入两个不同的特殊字符,即处理后的字符串tmp是下标从1开始的,原始字符串第一个字符应该在tmp[2]
hdu3068AC代码:
#include<stdio.h>
#include<string.h>
#include<math.h> #define min(a,b) a>b?b:a;
#define max(a,b) a>b?a:b;const int maxn=110010;
char str[maxn];//原字符串
char tmp[maxn<<1];//转换后的字符串
int Len[maxn<<1];
//转换原始串
int INIT(char *st)
{int i,len=strlen(st);tmp[0]='@';//字符串开头增加一个特殊字符,防止越界for(i=1;i<=2*len;i+=2){tmp[i]='#';tmp[i+1]=st[i/2];}tmp[2*len+1]='#';tmp[2*len+2]='$';//字符串结尾加一个字符,防止越界tmp[2*len+3]=0;return 2*len+1;//返回转换字符串的长度
}
//Manacher算法计算过程
int MANACHER(char *st,int len)
{int p_r=0,ans=0,po=0;//p_r是未涉及到的最左点 即 mx-1为po中心点作为回文串的右坐标 for(int i=1;i<=len;i++){ if(p_r>i){Len[i]=min(p_r-i,Len[po-(i-po)]);//Len[j]点中满足在po回文串内部的长度 }else { Len[i]=1;//如果i>=p_r,要从头开始匹配}while(st[i-Len[i]]==st[i+Len[i]])Len[i]++;if(Len[i]+i>p_r)//刷新po、p_r记录 {p_r=Len[i]+i;po=i;}ans=max(ans,Len[i]);}return ans-1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度 }int main(){while(gets(str)){INIT(str);//puts(tmp);printf("%d\n",MANACHER(tmp,strlen(tmp))); memset(str,'\0',sizeof(str));getchar();}return 0;}
部分内容借鉴于http://blog.csdn.net/dyx404514/article/details/42061017
马拉车(manacher)算法——最长回文(hdu3068)相关推荐
- manacher算法--最长回文子串
问题概述:输入一个字符串,输出它的最长回文子串 输入样例: 对应输出: abbaabcba ...
- Manacher 求最长回文子串算法
Manacher算法,是由一个叫Manacher的人在1975年发明的,可以在$O(n)$的时间复杂度里求出一个字符串中的最长回文子串. 例如这两个回文串"level"." ...
- manecher算法 最长回文子字符串
还没放假的时候就知道有这么一种算法,之前看了一下以为很难就没好好学,今天早上用心看了一下,发现其实很简单.学什么东西都应该静下心来好好理解好好学,才能保证高效率! 我主要是看这篇博客学的马拉车,我觉得 ...
- 中心扩散算法--最长回文子串
这篇看一下中心扩散算法. 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案. 示例 2:输入: " ...
- 算法62---最长回文子序列长度(子串)、回文子序列总共个数(子串)【动态规划】...
参考链接:https://www.cnblogs.com/AndyJee/p/4465696.html 一.题目:最长回文子序列长度 给定字符串,求它的最长回文子序列长度.回文子序列反转字符顺序后仍然 ...
- 常考数据结构与算法:最长回文子串
暴力解法: 列举所有的子串,判断是否为回文串,保存最长的回文串. /** 暴力解法: 列举所有的子串,判断是否为回文串,保存最长的回文串.*/public int getLongestPalindro ...
- 最长回文子串与最长回文子序列
文章目录 最长回文子串与最长回文子序列 最长回文子串 题目描述 dp解法 从中心扩展 马拉车算法 最长回文子序列 题目描述 dp 解法 递归思想 最长回文子串与最长回文子序列 最长回文子串 LeetC ...
- Manacher【p1210】回文检测
题目描述--->P1210 回文检测 分析: 看到回文显然想到了manacher算法(线性求解回文串问题 如果不了解还是去敲一下板子,学习一下比较好.-->manacher 题目要求我们求 ...
- 怎么判断一个字符串的最长回文子串是否在头尾_回文自动机入门
缘起 回文自动机(Palindrome auto machine PAM,有些地方称之为回文树)是回文问题的大杀器~ 本文使用一道很简单的题目入门这个精巧的数据结构. hdu 2163 Palind ...
最新文章
- JAVA学习笔记--数组初始化
- 恢复Linux误删除文件系列之scalpel工具
- java封装的特性,java的三大特性(封装、继承、多态)
- UVa1354 Mobile Computing
- 【控制】《多智能体系统的协同群集运动控制》陈杰老师-第2章-连通性保持条件下多智能体系统群集运动控制
- 双曲线和直线联立公式_高中圆锥曲线解题技巧之齐次化联立(四)
- 13、创建触发器(CREATE TRIGGER)
- ---innerHTML---
- php页面底部信息居中,css底部如何局中?css三种居中方法
- phpcms ajax 调取文章内容,Phpcms V9列表页使用GET标签调用指定文章内容的方法
- opencv 任意角度旋转图像
- 【华为大咖分享】3.如何做Code Review 与 结对编程?
- 数据解析(XML,JSON)
- 【AMAD】django-compressor -- 将JS和CSS文件压缩为一个缓存文件
- 实现线程的方式,源码分析:Runnable, Thread, Callable, Future, FutureTask
- python舆情分析系统设计与实现_基于Python的手机舆情系统综述
- Linux虚拟网络基础——Bridge
- JPEG文件中的EXIF(上)
- Ubuntu 禁用Guest用户
- ivr cti_简而言之,网络威胁情报(CTI)— 1
热门文章
- 8 SD配置-企业结构-分配-给公司代码分配销售组织
- 右边菜单_AI基础教程65:使用文字菜单编辑文字(七)查找字体
- response 流和写能一起吗_余甘果蜂蜜能一起吃吗?余甘果泡蜂蜜有什么功效?
- flask出现错误:cannot import name ‘ContextVar‘
- har文件解析工具_嵌入式MCU也能跑AI?STM32 Cube.AI工具包使用初探
- ceph docker mysql_使用Docker部署单机版Ceph
- python partition只能切割一次吗_Python3的字符串方法
- 两个list取交集_利用jieba计算两个句子的相似度
- youleb多风格响应式博客wordpress主题模板
- RiPro小八子主题V1.5.5美化版+优惠码折扣+工单系统+任务系统