Manacher算法:也叫 “马拉车”算法。

Manacher算法的应用范围要狭窄得多,但是它的思想和拓展kmp算法有很多共通支出,所以在这里介绍一下。Manacher算法是查找一个字符串的最长回文子串的线性算法。

什么是回文串:

所谓回文串,简单来说就是正着读和反着读都是一样的字符串,比如abba,noon等等,一个字符串的最长回文子串即为这个字符串的子串中,是回文串的最长的那个。

计算回文串的几种方式:其它几种方法请点击此链接

计算字符串的最长回文字串最简单的算法就是枚举该字符串的每一个子串,并且判断这个子串是否为回文串,这个算法的时间复杂度为O(n^3)的,显然无法令人满意,稍微优化的一个算法是枚举回文串的中点,这里要分为两种情况,一种是回文串长度是奇数的情况,另一种是回文串长度是偶数的情况,枚举中点再判断是否是回文串,这样能把算法的时间复杂度降为O(n2),但是当n比较大的时候仍然无法令人满意,Manacher算法可以在线性时间复杂度内求出一个字符串的最长回文字串,达到了理论上的下界。

1.Manacher算法原理与实现:

首先,Manacher算法提供了一种巧妙地办法,将长度为奇数的回文串和长度为偶数的回文串一起考虑,具体做法是,在原字符串的每个相邻两个字符中间插入一个分隔符,同时在首尾也要添加一个分隔符,分隔符的要求是不在原串中出现,一般情况下可以用#号。下面举一个例子:

(1)Len数组简介与性质

Manacher算法用一个辅助数组Len[i]表示以字符T[i]为中心的最长回文字串的最右字符到T[i]的长度,比如以T[i]为中心的最长回文字串是T[l,r],那么Len[i]=r-i+1。

对于上面的例子,可以得出Len[i]数组为:

Len数组有一个性质,那就是Len[i]-1就是该回文子串在原字符串S中的长度,至于证明,首先在转换得到的字符串T中,所有的回文字串的长度都为奇数,那么对于以T[i]为中心的最长回文字串,其长度就为2*Len[i]-1,经过观察可知,T中所有的回文子串,其中分隔符的数量一定比其他字符的数量多1,也就是有Len[i]个分隔符,剩下Len[i]-1个字符来自原字符串,所以该回文串在原字符串中的长度就为Len[i]-1。

有了这个性质,那么原问题就转化为求所有的Len[i]。下面介绍如何在线性时间复杂度内求出所有的Len。

(2)Len数组的计算

首先从左往右依次计算Len[i],当计算Len[i]时,Lenj已经计算完毕。设P为之前计算中最长回文子串的右端点的最大值,并且设取得这个最大值的位置为po,分两种情况:

第一种情况:i<=P

那么找到i相对于po的对称位置,设为j,

那么如果Len[j],如下图:

那么说明以j为中心的回文串一定在以po为中心的回文串的内部,且j和i关于位置po对称,由回文串的定义可知,一个回文串反过来还是一个回文串,所以以i为中心的回文串的长度至少和以j为中心的回文串一样,即Len[i]>=Len[j]。因为Len[j]如果Len[j]>=P-i 由对称性,说明以i为中心的回文串可能会延伸到P之外,而大于P的部分我们还没有进行匹配,所以要从P+1位置开始一个一个进行匹配,直到发生失配,从而更新P和对应的po以及Len[i]。

第二种情况: i>P

如果i比P还要大,说明对于中点为i的回文串还一点都没有匹配,这个时候,就只能老老实实地一个一个匹配了,匹配完成后要更新P的位置和对应的po以及Len[i]。

时间复杂度分析:

Manacher算法的时间复杂度分析和Z算法类似,因为算法只有遇到还没有匹配的位置时才进行匹配,已经匹配过的位置不再进行匹配,所以对于T字符串中的每一个位置,只进行一次匹配,所以Manacher算法的总体时间复杂度为O(n),其中n为T字符串的长度,由于T的长度事实上是S的两倍,所以时间复杂度依然是线性的。

算法实现:

class Solution {

public int Palindrome(List list, int mid,int l,int r){

//匹配得到回文串中点到一端的距离

while(l>=0&&r

//集合里面是包装类,不要用==

l--;

r++;

}

if(r==mid+1)

return 0;

return r-mid-1;//中点右边元素个数,r最后++了一次,所以需要-1

}

public String longestPalindrome(String s) {

int len=s.length();

List list=new ArrayList(len*2+1);

for(int i=0 ;i

list.add('#');

list.add(s.charAt(i));

}

list.add('#');

int[] ln=new int [len*2+1];

int r=-1; //最右回文串右端角标

int mid=-1;//最右回文串中点坐标

int maxMid=-1;//最长回文串中间坐标

int maxLen=-1;//最长回文串一端长度;

for(int j=0 ; j

if(j

int leftLen=ln[2*mid-j];

if(leftLen< r-j){

//对称左边回文串长度没有超出以r为右端点的回文串范围

ln[j]=leftLen;

}else{

//对称左边回文串长度超出范围不知道匹配不匹配,对超出部分进行匹配校验

ln[j]=Palindrome(list,j,j-(r-j),j+r-j);

}

}else{

//完全没有左边堆成回文串需要无脑匹配

ln[j]=Palindrome(list,j,j-1,j+1);//一半长度;

}

if(j+ln[j]>r){ //当前回文串右端与保存的右端取大

r=j+ln[j];

mid=j;

}

if(maxLen

maxLen=ln[j];

maxMid=j;

}

}

StringBuilder sb=new StringBuilder();

for(int z=maxMid-maxLen ; z<= maxMid+maxLen ;z++){

//去除#,得到最长回文子串

char ch=list.get(z).charValue();

if(ch!='#')

sb.append(ch);

}

return sb.toString();

}

}

马拉车java_算法-Manacher算法 / 马拉车算法(Java实现)相关推荐

  1. 最长回文 HDU - 3068(求最长回文串的长度【马拉车算法Manacher】)

    马拉车算法 Manacher's Algorithm 是用来查找一个字符串的最长回文子串的线性方法,由一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到了 ...

  2. Manacher Algorithm马拉车算法详解

    Manacher Algorithm马拉车算法详解 链接:https://www.zhihu.com/question/37289584/answer/465656849 中心扩展算法 我们先来看一个 ...

  3. 马拉车算法 Manacher

    马拉车算法 Manacher 具体分析:博客园 - BIT祝威 代码实现 - Manacher class Solution {public String longestPalindrome(Stri ...

  4. hash的算法 java_【数据结构与算法】一致性Hash算法及Java实践

    追求极致才能突破极限 一.案例背景 1.1 系统简介 首先看一下系统架构,方便解释: 页面给用户展示的功能就是,可以查看任何一台机器的某些属性(以下简称系统信息). 消息流程是,页面发起请求查看指定机 ...

  5. tsp java_基于贪心算法求解TSP问题(JAVA)

    前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 一.TPS问题 TSP问题(Travelling ...

  6. 内存分配算法java_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...

    一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...

  7. java python算法_用Python,Java和C ++示例解释的排序算法

    java python算法 什么是排序算法? (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions t ...

  8. 集合70多种推荐算法,东北大学老师用Java写了一个开源库,在GitHub上收获近1500个Star...

     [AI科技大本营导读]在经过一年多的开发工作之后,LibRec 3.0 版本终于发布了.LibRec 是一个基于 Java 的开源算法工具库,覆盖了 70 余个各类型推荐算法,可以有效解决评分预测 ...

  9. LeetCode算法题-Nth Digit(Java实现)

    这是悦乐书的第215次更新,第228篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第83题(顺位题号是400).找到无限整数序列的第n个数字1,2,3,4,5,6,7,8 ...

  10. A*算法解决八数码问题 Java语言实现

    A*算法解决八数码问题 Java语言实现 参考文章: (1)A*算法解决八数码问题 Java语言实现 (2)https://www.cnblogs.com/beilin/p/5981483.html ...

最新文章

  1. 数据中心水冷系统一次泵与二次泵的选择
  2. python爬虫网络请求超时是什么意思_爬虫请求超时设置
  3. 【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解
  4. 工作流的设计,业务流程图的绘制与编辑,工作流软件,工作流源代码组件库,开发平台,开发引擎...
  5. matlab频谱分析_罗德与施瓦茨两款新的信号和频谱分析仪 具有多种频率型号
  6. 依赖注入的三种方式_Java核心知识 Spring原理十 Spring 依赖注入四种方式
  7. Java 25 岁生日快乐!
  8. 不同级别的Java开发人员的应聘要求
  9. vue导入txt文本
  10. 圆锥曲线中的范围最值问题
  11. 数据结构 | 时间复杂度与空间复杂度
  12. 当老师帮学生作弊的时候
  13. demo爬腾讯视频,保存为MP4
  14. 计算机远程控制设计,远程控制软件的设计与实现
  15. HTML——多媒体语义化标签
  16. 安兔兔 android 4.4,适配智能电视 安兔兔评测V4.4.3发布
  17. 中软干两年有用吗_在中软国际的两年,是我成长最快的阶段
  18. 一句话解释IPD的核心内容
  19. 西门子西门子smart200和V90伺服程序
  20. Rhinoceros 建模简介1

热门文章

  1. JAVA——【案例】实现计算机系信息管理系统(教师和学生信息管理)
  2. 宝尚简讯-短期震荡在蓄势
  3. BLP读书笔记(一)——通过shell访问终端模式
  4. 软件无线电波测试软件,SDR软件无线电的测量
  5. 自动驾驶仿真(二)—— 基于PreScan与Simulink的联合仿真
  6. 在取证过程中,常见的一些注册表键值整理
  7. 投资 - 课程学习: 实现财富自由的科学路径-量化投资
  8. 通达OA 商务平台OA2017新版本简易评测(图文)
  9. Netty websocket 推送数据压缩以 js解压
  10. 【行测】图形找规律类题目