博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Manacher
阅读量:4706 次
发布时间:2019-06-10

本文共 1690 字,大约阅读时间需要 5 分钟。

文章参考:

江湖人称:马拉车算法

解决的问题:求一个字符串中的最长回文。

暴力的方法:遍历字符串,以当前字符为中心,向两边扩展直至不是回文。时间复杂度O(n^2)

Manacher算法:是记录并利用以前遍历过的回文,巧妙的达到一个加速的效果。时间复杂度O(n)

首先了解三个概念:

(1)回文半径数组:已求的回文的半径存储起来,为后面可以起到加速效果,避免重复的运算。

(2)最右回文半径:已求出来的回文中,最右边的回文半径

(3)最右回文半径的中心:顾名思义

图解一下流程:

C:是最右回文半径的中心,R:已经求出的最右回文半径的位置点,L:R关于C的对称点。

i:为当前遍历的下标位置,i' :关于C的对称点(前面遍历,已经求出来的回文半径)。

第一种情况:i' 的回文都在(L~R里面,直接得到 i 的回文半径就是 i' 的回文半径。如下图:

第二种情况:i' 的回文超出了(L~R)范围,部分在外面,直接得到 i 的回文半径就是 i 到 R的距离。如下图:

第三种情况:i' 的回文半径左边位置恰好与 L 重合i 就从R边界开始,向外扩,得到 i 的回文半径。

第四种情况:是 i 在 R 的右边,不在(L ~ R)的里面。方法是暴力向外扩。

以上就是所有的情况。

代码:

package basic_class_02;public class Code_04_Manacher {	public static char[] manacherString(String str) {		char[] charArr = str.toCharArray();		char[] res = new char[str.length() * 2 + 1];		int index = 0;		for (int i = 0; i != res.length; i++) {			res[i] = (i & 1) == 0 ? '#' : charArr[index++];		}		return res;	}	public static int maxLcpsLength(String str) {		if (str == null || str.length() == 0) {			return 0;		}		char[] charArr = manacherString(str);		int[] pArr = new int[charArr.length]; // 存储回文半径		int index = -1;    // 最右回文边界的中心点		int pR = -1;   // 最右回文边界		int max = Integer.MIN_VALUE;		for (int i = 0; i != charArr.length; i++) {			pArr[i] = pR > i ? Math.min(pArr[2 * index - i], pR - i) : 1;			while (i + pArr[i] < charArr.length && i - pArr[i] > -1) {				if (charArr[i + pArr[i]] == charArr[i - pArr[i]])					pArr[i]++;				else {					break;				}			}			if (i + pArr[i] > pR) {				pR = i + pArr[i];				index = i;			}			max = Math.max(max, pArr[i]);		}		return max - 1;	}	public static void main(String[] args) {		String str1 = "abc1234321ab";		System.out.println(maxLcpsLength(str1));	}}

 

转载于:https://www.cnblogs.com/horken/p/10706117.html

你可能感兴趣的文章
计算时间差
查看>>
Verilog MIPS32 CPU(七)-- DIV、DIVU
查看>>
03C#数据类型
查看>>
结构体命名时加了下划线
查看>>
设置控件样式表
查看>>
【模板-一些变量的声明和定义】
查看>>
StatePattern
查看>>
C# 二分查询
查看>>
Java 8 Stream API说明
查看>>
luoguP3959 [NOIP2017]宝藏(状压dp)
查看>>
一行最大公约数
查看>>
The Pilots Brothers' refrigerator 分类: ...
查看>>
Children of the Candy Corn 分类: POJ ...
查看>>
给傻瓜用的HTML5编程和JavaScript--第一部分--理解JS基础--第一章节--HTML,向JS说Hello...
查看>>
[Java] Frequently used method or solutions for issues
查看>>
POJ 3090 Visible Lattice Points (ZOJ 2777)
查看>>
解决Win8/8.1无法正确识别USB3.0的问题
查看>>
HDU 2587 - 很O_O的汉诺塔
查看>>
java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?
查看>>
centOS下实践查询版本/CPU/内存/硬盘容量等硬件信息
查看>>