manacher算法
来源:互联网 发布:鱼鹰软件 编辑:程序博客网 时间:2024/06/11 20:58
回文串在笔试编程题中很常见,昨天在牛客网上听了左神讲解的manacher算法,受益匪浅,下面就是我整理的manacher算法。
manacher算法是用来求一个字符串中的最长回文子串。
求字符串中的最长回文子串有两种方法:
(1)暴力求解法
即从左往右遍历字符串,对每一个点进行扩,求出每一个点的回文子串,找出最长回文子串,时间复杂度为O(n^2)
下面是用Java实现的:
package com.example.test;import java.util.Scanner;public class Test5 {static void LongestPalindromicSubstring(String str){char[] buf = str.toCharArray();int len = buf.length;int max = 0;String ans = new String() ;for(int i=0 ; i<len ; ++i){int j = i-1;int k = i+1;int cur = 0;while( j>=0 && k<len && buf[j]== buf[k]){cur++;j--;k++;}cur = cur*2+1;if(cur > max){max = cur;ans = str.substring(j+1,k);}}System.out.println(ans);}public static void main(String[] args) {// TODO Auto-generated method stubScanner scn = new Scanner(System.in);String str = scn.nextLine();LongestPalindromicSubstring(str);}}
(2)manacher算法:
从一个中心点向两边扩的时候会有奇回文和偶回文,为了统一解决这两种情况,我们可以给所求字符串的两端,和字符之间加上一个统一的字符,如:字符串abcdcbd,变成了#a#b#c#d#c#b#d#。这样转化后我们所求得的回文数除以2就是原始长度。
manacher算法的三个重点:
①回文半径数组。每一个点往外扩都会有相对的回文半径,将其回文半径存放在一个数组中。
②回文最右边界。每一个点在向外扩时,都会有右边界,如何某个点的右边界比先前的右边界往更右的方向。则我们应该更新最右边界。如下图扩a点时其回文右边界在第一个右括号处,扩b点时其回文右边界在第二个右括号处,扩b点时,最右回文边界被更新。
③回文最右边界中心。与②一致。需要注意的是,当两个或多个点的最右边界相同时,记录最早的那个。
manacher算法:分4种情况 时间复杂度O(n)
①当前点没有在回文最右边界里,扩。
从一个中心点向两边扩的时候会有奇回文和偶回文,为了统一解决这两种情况,我们可以给所求字符串的两端,和字符之间加上一个统一的字符,如:字符串abcdcbd,变成了#a#b#c#d#c#b#d#。这样转化后我们所求得的回文数除以2就是原始长度。
manacher算法的三个重点:
①回文半径数组。每一个点往外扩都会有相对的回文半径,将其回文半径存放在一个数组中。
②回文最右边界。每一个点在向外扩时,都会有右边界,如何某个点的右边界比先前的右边界往更右的方向。则我们应该更新最右边界。如下图扩a点时其回文右边界在第一个右括号处,扩b点时其回文右边界在第二个右括号处,扩b点时,最右回文边界被更新。
③回文最右边界中心。与②一致。需要注意的是,当两个或多个点的最右边界相同时,记录最早的那个。
manacher算法:分4种情况 时间复杂度O(n)
①当前点没有在回文最右边界里,扩。
②当前点i在回文最右边界里,其对称点i'在LR内,不扩,arr[i] = arr[i'];
③当前点i在回文最右边界里,其对称点i'在LR外,不扩,arr[i] = R-i;
④当前点i在回文最右边界里,其对称点i'压线,扩,因为无法确定
Java代码实现:
package com.example.test;import java.util.Scanner;public class Test5 {static void LongestPalindromicSubstring(String str){StringBuffer buffer = new StringBuffer();buffer.append("#");char[] buf = str.toCharArray();for(int i=0 ; i<buf.length ; ++i){buffer.append(buf[i]+"#");}buf = buffer.toString().toCharArray();int len = buf.length;int[] arr = new int[len];int rr = -1;int center = -1;for(int i=0 ; i<len ; ++i){int j = i-1;int k = i+1;int cur = 0;if(i > rr){ //没有在回文最右边界里,扩while( j>=0 && k<len && buf[j] == buf[k]){cur++;j--;k++;}arr[i] = cur;}else{ //在回文右边界里int ll = center - arr[center];int lcur = center - (rr-center);int llcur = lcur-arr[lcur];if( llcur > ll){ //当前节点的对称点的范围在LR中,不扩arr[i] = arr[lcur];}else if( llcur < ll){ //当前节点的对称点的范围在LR外,不扩arr[i] = rr-i;}else{while( j>=0 && k<len && buf[j] == buf[k]){ //当前节点的对称点的左范围和L重叠,扩cur++;j--;k++;}arr[i] = cur;}}if( i+cur > rr){rr = i +cur;center = i;}}int max = 0;for(int i=0;i<len;++i){if(arr[i]>max){max = i;}}System.out.println(str.substring((max-arr[max])/2, (max+arr[max])/2));}public static void main(String[] args) {// TODO Auto-generated method stubScanner scn = new Scanner(System.in);String str = scn.nextLine();LongestPalindromicSubstring(str);}}
上面的图画的有点丑,应该可以看懂
阅读全文
0 0
- Manacher算法
- Manacher算法
- Manacher算法
- Manacher算法
- Manacher 算法
- manacher算法
- manacher 算法
- Manacher算法
- manacher算法
- manacher算法
- manacher算法
- Manacher 算法
- Manacher算法
- manacher算法
- Manacher算法
- manacher算法
- Manacher算法
- Manacher算法:
- 获得WebAPI原始POST请求BODY的JSON内容
- 程序解耦 购物车操作 生成订单 (网上商城三)
- ifix5.8 修改节点名,新建工程
- 依赖
- leetcode 204. Count Primes 这道题很有趣 + 搜索空间递减
- manacher算法
- html5/Css3 3D立方体转圈
- iOS11 不能定位如何解决
- vue.js的安装步骤
- 读取Java文件到byte数组的三种方式(转载)
- web前段 javascript入门笔记+少部分数组知识
- 完整的大数据云计算.技术图谱
- 删除
- ViewPager的简单使用