
- 資料結構與演算法
- 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
廣告