这个题目主要是运用manacher算法,又称为马拉车算法,下面对算法进行介绍。

manacher算法

  首先,定义一些变量,假设当前访问的是第ii个位置:
1.p[i]:1.p[i]:表示以第ii个字符为中心的最长回文子串的半径。
2.maxRight:i2.maxRight:i之前(包括ii)所对应的回文子串所能到达的最右边的位置。

  然后假设现在要求以第j(假设j=i+k)j(假设j=i+k)个字符为中心的最长回文串的半径p[j]p[j],假设在jj之前,是以第ii个字符为中心的最长回文串能够到达最右边的位置,即位置maxRightmaxRight,则说明maxRight=i+p[i]maxRight=i+p[i]。要快速的求出以第jj个字符为中心的最长回文子串半径,一定要利用好之前已经求得的回文子串。对jj的位置进行讨论:
  1.j>=maxRight:1.j>=maxRight:由于maxRight=i+p[i]maxRight=i+p[i],所以jj所处的位置不在第ii个字符为中心的最长回文子串中,无法利用以前求得的经验,这是得用一般的方法来求p[j]p[j],即初始化p[j]=1p[j]=1,因为此时只包含本身。然后依次判断左右两边的字符是否相等,来确定p[j]p[j]的最长子串半径大小。

  2.j<maxRight:2.j由于maxRight=i+p[i]maxRight=i+p[i],所以jj所处的位置在第ii个字符为中心的最长回文子串中。此时,我们可以利用回文串的称关系来求解。因为已经假设:j=i+kj=i+k,所以求p[j],即p[i+k]p[j],即p[i+k]时,可以利用其关于ii的对称点i−ki-k所对应的p[i−k]p[i-k]值来求解。此时需要对(i−k−p[i−k])(i-k-p[i-k])和(i−p[i])(i-p[i])的大小分三种情况来讨论。

  2.1:(i−k−p[i−k])>(i−p[i]):2.1:(i-k-p[i-k])>(i-p[i]):如图所示

此时p[i−k]p[i-k]对应的最长回文串被p[i]p[i]对应的最长回文串的左半部分完全包围,根据回文的对称性,p[i+k]p[i+k]也应该被右半部分完全包围,并且p[i−k]=p[i+k]=p[j]p[i-k]=p[i+k]=p[j],很好理解,不需要证明。

  2.2:(i−k−p[i−k])=(i−p[i]):2.2:(i-k-p[i-k])=(i-p[i]):如图所示

此时p[i−k]p[i-k]对应的最长回文串还是被p[i]p[i]对应的最长回文串所包围,所以对应的p[i+k]p[i+k]的最长回文串至少也会到达i+p[i]i+p[i]的位置,即maxRightmaxRight处,但是因为maxRightmaxRight位置之后的字符情况未知,可能还会有与以i+ki+k为中心的左边位置的字符相等,所以p[i+k]p[i+k]的值可能还会更长,此时需要再次比较ch[left]==ch[right]ch[left]==ch[right]的情况来判断是否会更长,此时p[i+k]>=p[i−k]p[i+k]>=p[i-k],应该从(i+k−p[i−k])和(i+k+p[i−k])(i+k-p[i-k])和(i+k+p[i-k])两个位置进行左右比较。

  2.3:(i−k−p[i−k])=(i−p[i]):2.3:(i-k-p[i-k])=(i-p[i]):如图所示

此时,p[i]p[i]对应的最长回文子串的左半部分无法完整的包含p[i−k]p[i-k]对应的最长回文子串,此时p[i+k]=p[i]−kp[i+k]=p[i]-k,即最长回文子串半径仅仅包含i−p[i]i-p[i]到i−ki-k之间的那一小段。能不能更长呢,答案是否定的,下面给予证明。
  假设p[i+k]p[i+k]的值能够更大,即p[i+k]>p[i]−kp[i+k]>p[i]-k,如图所示,这相当于在(i+p[i])(i+p[i])的位置后面延伸了一小段(图中最右边的那段小粗横线),根据根据对称性,图中另外几段小粗黑线必须也有的。假设从左到右依次标注那几段小黑线为L1,L2,L3,L4L_1,L_2,L_3,L_4,现在假设L4L_4是存在的,假设其值为ABCABC,则根据回文的对称性,L3L_3的值为CBACBA,L2L_2的值为ABCABC,L1L_1的值为CBACBA,可以发现L1L_1和L4L_4也是回文对称的,所以以位置ii为中心的最长回文串应该更长,不应该是p[i]p[i],而应该是p[i]+3p[i]+3,因为ABCABC的长度为3,但是这明显最原始的假设不符合,因为最原始假设就是为p[i]p[i]。所以p[i+k]p[i+k]只能等于p[i]−kp[i]-k。

  然后对上述三种情况进行汇总:

p[i+k]=⎧⎩⎨p[i−k],≥p[i−k],p[i]−k,p[i]-k>p[i-k]p[i]-k=p[i-k]p[i]-k<p[i-k]

p[i+k]= \begin{cases} p[i-k], & \text {p[i]-k>p[i-k]} \\ \geq p[i-k], & \text{p[i]-k=p[i-k]}\\p[i]-k,& \text{p[i]-k

观察总结之后发现,p[i+k]=min{p[i−k],p[i]−k}p[i+k]=min \{p[i-k],p[i]-k\} ,当然,对于第二种情况,即可能更长的情况,其实可能会更大,我们将上面三种也统一,在赋值完之后,在进行左右比较,因为对于第一种和第三种情况,进行左右比较时肯定不相等,不影响值的变化,对于第二种情况进行左右比较就可以得到真实最长半径。

2.字符串预处理

  在求最长回文子串的时候,我们还得对区分以单字符为中心的最长回文子串和以双字符为中心的最长回文子串进行判断,为了便于处理,我们可以通过在字符串中加入统一的字符,将奇偶情况统一为以单字符为中心的最长子串。例如:对于字符串“abbc”,我们可以通过加入’#’字符,将其变为”#a#b#b#c#”,这样就变为以单字符为中心;对于字符”aba”,也通过加入’#’,将其变为”#a#b#a#”,仍然是以单字符为中心。就完成了统一,也便于使用manacher算法,因为该算法就是以单字符为中心。
  但是由于最左边和最右边都是’#’,这样在进行左右判断的时候,就会left−−和right++left--和right++成立,会出现越界的情况。为了避免这种越界的发生,我们可以在两端再次添加两个不同的字符,例如最左边添加’@’,最右边添加’=’,此时”aba”处理之后的结果为”@#a#b#a#=”。

3.代码实现

    public static String solve(String ss) {/** 加#号,使得两种情况统一处理* 如"aa"变为"#a#a#"* 再如"aba"变为"#a#b#a#"* 防止越界,在首部再加上@,尾部加上$,只要不同即可,防止越界*/char[] cs = ss.toCharArray();int len = cs.length * 2 + 3;                     //首部,尾部加一个不同的字符,防止越界char[] res = new char[len];res[0] = '@';res[len - 1] = '$';for(int i = 1; i < len - 1; i++) {if((i&1) != 0) {                            //如果是奇数res[i] = '#';}else {                                      //偶数res[i] = cs[i / 2 - 1];}}int maxRight = 0;                               //能到的最右边           int longestCenter = 0;                          //最长的中心int longest = 0;                                //最长int nowCenter = 0;                              //到达最右边对应的中心int[] dp = new int[len];                        //以i位置就中心的最长回文串for(int i = 1; i < len - 1; i++) {if(maxRight > i) {dp[i] = Math.min(dp[2*nowCenter - i], maxRight - i);}else {dp[i] = 1;}//考虑以此为中心,继续递增,因为恰好在边界上需要考虑while(res[i + dp[i]] == res[i - dp[i]]) {dp[i]++;}if(dp[i] + i > maxRight) {maxRight = dp[i] + i;nowCenter = i;}if(longest < dp[i]) {longest = dp[i];longestCenter = i;}}StringBuffer sb = new StringBuffer();for(int i = longestCenter - longest + 1; i < longestCenter + longest - 1; i++) {if(res[i] != '#')sb.append(res[i]);}return sb.toString();}

leetcode5:最长回文子串相关推荐

  1. LeetCode5. 最长回文子串

    LeetCode5. 最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: " ...

  2. leetcode5. 最长回文子串(动态规划)

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &qu ...

  3. LeetCode--5.最长回文子串(滑动窗口)

    最长回文子串(C) 1. 题目描述 2. 题目分析 3. C语言实现 1. 题目描述 难度:中等 2. 题目分析 根据题目,需要注意的有以下几点: 回文子串 回文子串就是正着读和反着读是一样的,比如a ...

  4. python最长回文子串leetcode_Python版LeetCode5. 最长回文子串

    本文转载自[微信公众号:机器学习算法与Python精研,ID:AITop100]经微信公众号授权转载,如需转载与原文作者联系 题目: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的 ...

  5. leetcode--5. 最长回文子串

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &qu ...

  6. Leetcode--5. 最长回文子串(java)

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &qu ...

  7. 马拉车java_leetcode-5 最长回文子串-画蛇添足的马拉车算法

    leetcode-5 最长回文子串 题目 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: &q ...

  8. 怎么判断一个字符串的最长回文子串是否在头尾_最长回文字串/子序列问题(leetcode5,9,519)

    leetcode 5 最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: " ...

  9. LeetCode5-最长回文子串原理及Python实现

    LeetCode5(medium)-最长回文子串 题目 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 思路 中心扩展法 遍历字符串,依次把每个字符作为中心. ...

最新文章

  1. webstrom 中 plugins error 设置里 Languages Frameworks里面没有JavaScript?
  2. java -jar debug_java – 如何在运行时调试jar?
  3. 分析数万条国庆旅游评论数据后,我发现了“坑爹”景点背后的秘密
  4. 概率论基础3----分布
  5. kali自带发包工具tcpreplay
  6. ggplot2设置坐标轴范围_ggplot2——双坐标轴?
  7. java excel 取消科学计数法_java使用poi解析或处理excel的时候,如何防止数字变成科学计数法的形式...
  8. MT6739充电IC集成步骤
  9. “人工智能”•从入门到入土 –导言
  10. 关于小米文件管理器的介绍及源码下载
  11. 运动神经元有哪些特征 容易与哪些疾病混淆
  12. JAVAscript中的this指向和this指向的修改
  13. 【RVM预测】基于粒子群算法优化相关向量机RVM实现数据回归预测附matlab代码
  14. 【稳定性day4】美团外卖高可用的演进之路 - 日活两千万的挑战
  15. 如何租用云服务器并进行远程连接
  16. 吴金贵有望二次助教国足 成顶替刘春明热门人选
  17. 转载 英语一千句
  18. windows powershell批量添加dns记录
  19. vmware Workstation设置bios启动
  20. 0002 计算长方形周长和面积

热门文章

  1. DBUtils 主要结果集说明
  2. Windows下nginx的安装及使用方法入门
  3. 容器编排技术 -- kubernetes 通过环境变量向容器暴露 Pod 信息
  4. Android udp json+数组 ---gt;bytes发送数据
  5. 【python】Macbook的Anaconda查看、创建和管理python环境
  6. nuxt vue ssr实现
  7. 【PHP】网站防止QQ拦截防红跳转代码
  8. “The server requested authentication method unknown to the client.”的解决方案
  9. C#LeetCode刷题之#496-下一个更大元素 I(Next Greater Element I)
  10. Django之models