Manacher算法解决最长回文子串长度问题

马拉车(Manacher)算法(具体算法流程看这个哥们的:https://blog.csdn.net/qq_35065720/article/details/104205920):

算法解决:在一个字符串中找到最长的回文字符串。

实现策略:

以每个位置作为中心,向两边扩展,可以确定奇回文,但是偶回文无法这样做。

解决方法:在字符串中间及两边插入某种字符,此时可以按照这种方法进行扩展。此时无论奇回文还是偶回文都可以找到。

例如11211,此时添加任意字符在两边#1#1#2#1#1#此时均可以进行回文判断。

C++代码实现:

class Solution1 {
public:
	char* manacherString(string str) {
		char* charArr = new char[str.size() * 2 + 1];
		int str_len = str.size();
		for (int i = 1; i <= str_len; i++) {
			charArr[2 * i] = str[i - 1];
			charArr[2 * i + 1] = ‘#‘;
		}
		return charArr;
	}

	int maxLcpsLength(string str) {
		if (str.size() == 0) {
			return 0;
		}
		char* charArr = manacherString(str);
		vector<int> pArr(strlen(charArr)); // 回文半径数组
		int C = -1;
		int R = -1;
		int max_val = INT_MIN;
		for (int i = 0; i != strlen(charArr); i++) {
			pArr[i] = R > i ? min(pArr[2 * C - i], R - i) : 1;
			// R > i 表示 i在回文右边界里面,有一个不用验的区域
			//  2*C-i 为 i关于C的对称点i‘,两个瓶颈:1.i‘的回文半径 2. R到我(i)的距离
			while (i + pArr[i] < strlen(charArr) && i - pArr[i] > -1) { // 左右两边都不越界
				if (charArr[i + pArr[i]] == charArr[i - pArr[i]]) { // 在不用验的区域下再扩一下
					pArr[i]++;
				}
				else {
					break;
				}
			}
			if (i + pArr[i] > R) {
				R = i + pArr[i]; // 更新右边界
				C = i;           // 更新中心位置
			}
			max_val = max(max_val, pArr[i]); // 全局最大值
		}
		return max_val - 1;
	}
};

  

原文地址:https://www.cnblogs.com/E-Dreamer-Blogs/p/12642756.html

时间: 2024-11-09 02:54:00

Manacher算法解决最长回文子串长度问题的相关文章

数据结构--Manacher算法(最长回文子串)

在字符串中求出其最长回文子串 可能是奇回文也可能是偶回文,要考虑全面 暴力解法:(因为存在奇回文和偶回文的问题,所以不好找,有一个技巧,就是想字符串中每个字符之间添加一个符号(任意符号,也可以是字符串中的符号),然后在每个位置向两端开始扩充) 答案就是最大值/2 Manacher算法: 字符串中每个字符串之间也要加上一个字符 回文直径:从某个位置开始向两边扩的最大长度 1. 回文半径数组:arr[],以每个位置为中心能扩出来的回文半径的长度 2. 最右回文右边界R:所有回文半径中,最靠右的位置

Manacher&#39;s algorithm: 最长回文子串算法

Manacher 算法是时间.空间复杂度都为 O(n) 的解决 Longest palindromic substring(最长回文子串)的算法.回文串是中心对称的串,比如 'abcba'.'abccba'.那么最长回文子串顾名思义,就是求一个序列中的子串中,最长的回文串.本文最后用 Python 实现算法,为了方便理解,文中出现的数学式也采用 py 的记法. 在 leetcode 上用时间复杂度 O(n**2).空间复杂度 O(1) 的算法做完这道题之后,搜了一下发现有 O(n) 的算法.可惜

[算法]manachar最长回文子串

现给定一个已知的字符串str[],现在想要在O(n)的时间复杂度之内求出一个最长的回文子字符串(正着和倒着顺序读一致). Manacher最早发现了可以用O(n)的时间复杂度来解决该问题,所以这种方法称之为Manacher算法. #include <iostream> using namespace std; int min(int a, int b){ return a > b ? b : a; } char* preproccess(char* src, char* des){ in

【算法】最长回文子串 longest palindrome substring

对于字符串S, 要找到它最长的回文子串,能想到的最暴力方法,应该是对于每个元素i-th都向左向右对称搜索,最后用一个数组span 记录下相对应元素i-th为中心的回文子串长度. 那么问题来了: 1. 这样的方法,对于奇回文子串和偶回文子串的处理不一样,比如所"acbca" 和"acbbca" 2. 计算冗余,e.g. "sscssabcccchccccba"中, 自左向右遍历计算的话,会发现, "abcccchccccba"是

manacher算法求最长回文子序列

一:背景 给定一个字符串,求出其最长回文子串.例如: s="abcd",最长回文长度为 1: s="ababa",最长回文长度为 5: s="abccb",最长回文长度为 4,即bccb. 以上问题的传统思路大概是,遍历每一个字符,以该字符为中心向两边查找.其时间复杂度为O(n^2),效率很差. 1975年,一个叫Manacher的人发明了一个算法,Manacher算法(中文名:马拉车算法),该算法可以把时间复杂度提升到O(n).下面来看看马拉车

(算法)最长回文子串

题目: 求一个字符串的最长回文子串 思路: 1.暴力枚举 最容易想到的就是暴力破解,列举每一个子串,然后根据回文的定义判断是不是回文,找到最长的那个. 求每一个子串的时间复杂度为O(N^2),判断子串是不是回文的时间复杂度为O(N),所以时间复杂度为O(N^3). 2.动态规划 回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文字符串,那么P[i+1,j-1]也是回文字符串.这样最长回文子串就能分解成一系列子问题了. 这样需要额外的空间是O(N^2),时间复杂度也是O

算法题--最长回文子串

题目描述 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设?s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案. 示例 2: 输入: "cbbd" 输出: "bb" 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring

【算法】最长回文子串的判断

描述: 比如:"12212321"的最长回文子串为"12321"长度为5 <pre name="code" class="cpp">int LongestPalindrome(string s) { int max=0; if (s.length() >= 1) { for(int i=0;i<s.length();i++) { int l; for(l=0;(i-l>=0 &&

算法练习——最长回文子串

题目: 给定一个字符串 s,找到 s 中最长的回文子串. 示例 1: 输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案. 示例 2: 输入: "cbbd" 输出: "bb" 方法1:暴力求解 思路:可以通从两端到中间遍历字符串,如果碰到字符串是回文串,则该回文串一定是是最长回文串. 效果:判断的整个过程其实有三个内部循环,时间复杂度接近  O(n^3) ,空间复杂度O(n) p