- 数据结构与算法
- DSA - 首页
- DSA - 概述
- DSA - 环境设置
- DSA - 算法基础
- DSA - 渐进分析
- 数据结构
- DSA - 数据结构基础
- DSA - 数据结构和类型
- DSA - 数组数据结构
- 链表
- DSA - 链表数据结构
- DSA - 双向链表数据结构
- DSA - 循环链表数据结构
- 栈与队列
- DSA - 栈数据结构
- DSA - 表达式解析
- DSA - 队列数据结构
- 搜索算法
- DSA - 搜索算法
- DSA - 线性搜索算法
- DSA - 二分搜索算法
- DSA - 插值搜索
- DSA - 跳跃搜索算法
- DSA - 指数搜索
- DSA - 斐波那契搜索
- DSA - 子列表搜索
- DSA - 哈希表
- 排序算法
- DSA - 排序算法
- DSA - 冒泡排序算法
- DSA - 插入排序算法
- DSA - 选择排序算法
- DSA - 归并排序算法
- DSA - 希尔排序算法
- DSA - 堆排序
- DSA - 桶排序算法
- DSA - 计数排序算法
- DSA - 基数排序算法
- DSA - 快速排序算法
- 图数据结构
- DSA - 图数据结构
- DSA - 深度优先遍历
- DSA - 广度优先遍历
- DSA - 生成树
- 树数据结构
- DSA - 树数据结构
- DSA - 树的遍历
- DSA - 二叉搜索树
- DSA - AVL树
- DSA - 红黑树
- DSA - B树
- DSA - B+树
- DSA - 伸展树
- DSA - 字典树
- DSA - 堆数据结构
- 递归
- DSA - 递归算法
- DSA - 使用递归实现汉诺塔
- DSA - 使用递归实现斐波那契数列
- 分治法
- DSA - 分治法
- DSA - 最大最小问题
- DSA - Strassen矩阵乘法
- DSA - Karatsuba算法
- 贪心算法
- DSA - 贪心算法
- DSA - 旅行商问题(贪心算法)
- DSA - Prim最小生成树
- DSA - Kruskal最小生成树
- DSA - Dijkstra最短路径算法
- DSA - 地图着色算法
- DSA - 分数背包问题
- DSA - 带截止日期的作业排序
- DSA - 最佳合并模式算法
- 动态规划
- DSA - 动态规划
- DSA - 矩阵链乘法
- DSA - Floyd-Warshall算法
- DSA - 0-1背包问题
- DSA - 最长公共子序列算法
- DSA - 旅行商问题(动态规划)
- 近似算法
- DSA - 近似算法
- DSA - 顶点覆盖算法
- DSA - 集合覆盖问题
- DSA - 旅行商问题(近似算法)
- 随机算法
- DSA - 随机算法
- DSA - 随机快速排序算法
- DSA - Karger最小割算法
- DSA - Fisher-Yates洗牌算法
- DSA有用资源
- DSA - 问答
- DSA - 快速指南
- DSA - 有用资源
- DSA - 讨论
Manacher算法
Manacher算法用于查找给定字符串中的最长回文子串。回文是指与自身反转相等的字符串,回文子串是指也是回文的字符串的子串,例如“aabaaccaabaa”中的“aabaa”。该算法由Glenn K. Manacher于1975年提出。
Manacher算法是如何工作的?
查找最长回文子串的朴素方法是检查给定字符串的每个可能的子串,然后验证它是否为回文。但是,这将消耗更多的时间和空间。
Manacher算法通过利用一些观察和技巧,以线性时间,即O(n),解决了这个问题。主要思想是利用回文的对称性来避免不必要的比较。
算法
Manacher算法涉及以下步骤:
首先,我们通过在每对字符之间以及字符串的开头和结尾插入一个特殊字符(例如“#”)来预处理给定的字符串。这确保了新字符串中的每个回文都具有奇数长度和唯一的中心。例如,字符串“abba”变为“#a#b#b#a#”。
接下来,我们创建一个名为P[]的数组,其长度与新字符串相同,其中P[i]存储以新字符串中位置i为中心的回文子串的最长长度。我们初始化P[0] = 0和P[1] = 1,因为前两个字符始终是单字符回文。
然后,我们从左到右遍历新字符串。
对于每个位置i,找到i相对于当前最右回文中心的镜像位置j。
接下来,将P[j]的值复制到P[i],除非它超过边界R。
通过比较i + P[i]两侧的字符来扩展以i为中心的回文。如果它们匹配,我们将P[i]增加1并重复此步骤,直到它们不匹配或到达字符串的末尾。
示例
在下面的示例中,我们将实际演示Manacher算法如何在各种编程语言中工作。
#include<stdio.h> #include<string.h> // Function to return the minimum of two integers int minm(int a, int b) { return (a<b)?a:b; } // Function to find longest palindromic substring void findLongPalindrome(char orgnlString[]) { int n = strlen(orgnlString); if(n == 0) // If the string is empty, return an empty string return; n = 2*n + 1; // Array to store the length of palindrome int lenPalndrm[n]; // Initialization of first two positions lenPalndrm[0] = 0; lenPalndrm[1] = 1; int centerIndex = 1; int rightIndex = 2; int right = 0, left; int maxPalLength = 0, maxCenterIndex = 0; int start = -1, end = -1, diff = -1; // Loop through the string for (right = 2; right < n; right++) { left = 2*centerIndex-right; lenPalndrm[right] = 0; diff = rightIndex - right; // If difference is greater than 0, update length at current position if(diff > 0) lenPalndrm[right] = minm(lenPalndrm[left], diff); // While the palindrome can be extended, extend it while ( ((right + lenPalndrm[right]) < n && (right - lenPalndrm[right]) > 0) && ( ((right + lenPalndrm[right] + 1) % 2 == 0) || (orgnlString[(right + lenPalndrm[right] + 1)/2] == orgnlString[(right - lenPalndrm[right] - 1)/2] ))) { lenPalndrm[right]++; } // If the palindrome length at the current position is greater than the maximum palindrome length, update the maximum palindrome length and its center index if(lenPalndrm[right] > maxPalLength) { maxPalLength = lenPalndrm[right]; maxCenterIndex = right; } // If the right boundary of the palindrome at the current position is greater than the right index, update the center index and the right index if (right + lenPalndrm[right] > rightIndex) { centerIndex = right; rightIndex = right + lenPalndrm[right]; } } start = (maxCenterIndex - maxPalLength)/2; end = start + maxPalLength - 1; // maximum palindrome char maxPalindrm[end-start+2]; strncpy(maxPalindrm, &orgnlString[start], end-start+1); maxPalindrm[end-start+1] = '\0'; printf("Longest palindrome is: %s\n", maxPalindrm); } int main() { char orgnlString[] = "AAAABCAEAAABCBDDAAAAABC"; // method calling findLongPalindrome(orgnlString); return 0; }
#include<iostream> using namespace std; // Function to return the minimum of two integers int minm(int a, int b) { return (a<b)?a:b; } // Function to find longest palindromic substring string findLongPalindrome(string orgnlString) { int n = orgnlString.size(); if(n == 0) // If the string is empty, return an empty string return ""; n = 2*n + 1; // Array to store the length of palindrome int lenPalndrm[n]; // Initialization of first two positions lenPalndrm[0] = 0; lenPalndrm[1] = 1; int centerIndex = 1; int rightIndex = 2; // Variables to store the current right and left positions int right = 0, left; // Variables to store maximum palindrome length and its center index int maxPalLength = 0, maxCenterIndex = 0; int start = -1, end = -1, diff = -1; // Loop through the string for (right = 2; right < n; right++) { // Calculate the corresponding left position left = 2*centerIndex-right; lenPalndrm[right] = 0; diff = rightIndex - right; // If difference is greater than 0, update length at current position if(diff > 0) lenPalndrm[right] = min(lenPalndrm[left], diff); // While the palindrome can be extended, extend it while ( ((right + lenPalndrm[right]) < n && (right - lenPalndrm[right]) > 0) && ( ((right + lenPalndrm[right] + 1) % 2 == 0) || (orgnlString[(right + lenPalndrm[right] + 1)/2] == orgnlString[(right - lenPalndrm[right] - 1)/2] ))) { lenPalndrm[right]++; } // If the palindrome length at the current position is greater than the maximum palindrome length, update the maximum palindrome length and its center index if(lenPalndrm[right] > maxPalLength) { maxPalLength = lenPalndrm[right]; maxCenterIndex = right; } // If the right boundary of the palindrome at the current position is greater than the right index, update the center index and the right index if (right + lenPalndrm[right] > rightIndex) { centerIndex = right; rightIndex = right + lenPalndrm[right]; } } // Calculate the start and end indices of the maximum palindrome start = (maxCenterIndex - maxPalLength)/2; end = start + maxPalLength - 1; string maxPalindrm; // Construct the maximum palindrome for(int i=start; i<=end; i++) maxPalindrm += orgnlString[i]; // Returning maximum palindrome return maxPalindrm; } int main(int argc, char *argv[]) { string orgnlString, palindrome; orgnlString = "AAAABCAEAAABCBDDAAAAABC"; // method calling palindrome = findLongPalindrome(orgnlString); cout << "Longest palindrome is: " << palindrome << endl; }
import java.util.Arrays; public class Main { // Function to find longest palindromic substring public static String findLongestPalindrome(String orgnlString) { // If the string is null or empty, return an empty string if (orgnlString == null || orgnlString.length() == 0) return ""; char[] s2 = addBoundaries(orgnlString.toCharArray()); // Array to store the length of palindrome int[] lenPlandrm = new int[s2.length]; int centerIndex = 0, right = 0; // to compare if two elements are the same int m = 0, n = 0; // Loop through the string for (int i = 1; i<s2.length; i++) { if (i > right) { lenPlandrm[i] = 0; m = i - 1; n = i + 1; } else { int i2 = centerIndex * 2 - i; if (lenPlandrm[i2] < (right - i - 1)) { lenPlandrm[i] = lenPlandrm[i2]; m = -1; } else { lenPlandrm[i] = right - i; n = right + 1; m = i * 2 - n; } } // While the palindrome can be extended, extend it while (m >= 0 && n < s2.length && s2[m] == s2[n]) { lenPlandrm[i]++; m--; n++; } // If the right boundary of the palindrome at the current position is greater than the right index, update the center index and the right index if ((i + lenPlandrm[i]) > right) { centerIndex = i; right = i + lenPlandrm[i]; } } int len = 0; centerIndex = 0; // Find the maximum palindrome length and its center index for (int i = 1; i<s2.length; i++) { if (len < lenPlandrm[i]) { len = lenPlandrm[i]; centerIndex = i; } } // Construct the maximum palindrome char[] maxPalindrm = Arrays.copyOfRange(s2, centerIndex - len, centerIndex + len + 1); // Returning maximum palindrome return String.valueOf(removeBoundaries(maxPalindrm)); } // Function to add boundaries to handle even length palindromes private static char[] addBoundaries(char[] cs) { if (cs == null || cs.length == 0) return "||".toCharArray(); char[] cs2 = new char[cs.length * 2 + 1]; for (int i = 0; i < (cs2.length - 1); i = i + 2) { cs2[i] = '|'; cs2[i + 1] = cs[i / 2]; } cs2[cs2.length - 1] = '|'; return cs2; } // Function to remove the added boundaries from the result private static char[] removeBoundaries(char[] cs) { if (cs == null || cs.length < 3) return "".toCharArray(); char[] cs2 = new char[(cs.length - 1) / 2]; for (int i = 0; i < cs2.length; i++) { cs2[i] = cs[i * 2 + 1]; } return cs2; } public static void main(String[] args) { String orgnlString = "AAAABCAEAAABCBDDAAAAABC"; System.out.println("Longest palindrome is: " + findLongestPalindrome(orgnlString)); } }
def add_boundaries(cs): if cs is None or len(cs) == 0: return ['|', '|'] cs2 = ['|'] * (len(cs) * 2 + 1) for i in range(len(cs)): cs2[i * 2 + 1] = cs[i] return cs2 def remove_boundaries(cs): if cs is None or len(cs) < 3: return "" cs2 = [''] * ((len(cs) - 1) // 2) for i in range(len(cs2)): cs2[i] = cs[i * 2 + 1] return ''.join(cs2) def find_longest_palindrome(orgnl_string): if orgnl_string is None or len(orgnl_string) == 0: return "" s2 = add_boundaries(list(orgnl_string)) len_palandrm = [0] * len(s2) center_index = 0 right = 0 m = 0 n = 0 for i in range(1, len(s2)): if i > right: len_palandrm[i] = 0 m = i - 1 n = i + 1 else: i2 = center_index * 2 - i if len_palandrm[i2] < (right - i - 1): len_palandrm[i] = len_palandrm[i2] m = -1 else: len_palandrm[i] = right - i n = right + 1 m = i * 2 - n while m >= 0 and n < len(s2) and s2[m] == s2[n]: len_palandrm[i] += 1 m -= 1 n += 1 if (i + len_palandrm[i]) > right: center_index = i right = i + len_palandrm[i] length = 0 center_index = 0 for i in range(1, len(s2)): if length < len_palandrm[i]: length = len_palandrm[i] center_index = i max_palindrm = s2[center_index - length : center_index + length + 1] return remove_boundaries(max_palindrm) orgnl_string = "AAAABCAEAAABCBDDAAAAABC" print("Longest palindrome is:", find_longest_palindrome(orgnl_string))
输出
Longest palindrome is: AAAAA
广告