Manacher算法—最长回文串

若字符串长度为n,则算法的时间复杂度为o(n)

假设有一个字符串abaaba

先把该字符串变成$  #  a  #  b  #  a  #  a  #  b  #  a  #

第一个字符设为‘$’,防止计算的时候数组越界

再计算p数组,先给出p数组的答案

i为坐标,ma数组放改变后的字符串,p数组代表以该字符为中心,向右和向左延伸p[i]个,是回文串

i       0  1  2  3  4  5  6  7  8  9  10 11 12 13
ma[]   $  #  a  #  b  #  a   #  a  #  b   #   a   #
p[]      1  1  2  1  4  1  2   7  2  1   4  1   2   1

附上完整代码

 1 #include <bits/stdc++.h>
 2
 3 using namespace std;
 4
 5 typedef long long LL;
 6 const int maxn = 110000;
 7 char ma[maxn*2];
 8 int p[maxn*2];
 9
10 void Manacher(char *s,int len) {
11     int l = 0;
12     ma[l++] = ‘$‘;
13     ma[l++] = ‘#‘;
14     for(int i = 0; i < len; i++) {
15         ma[l++] = s[i];
16         ma[l++] = ‘#‘;
17     }
18     ma[l] = 0;
19     int mx = 0,id = 0;
20     for(int i = 0; i < l; i++) {
21         p[i] = mx > i?min(p[2*id - i],mx - i) : 1;//这一步最为关键
22         while(ma[i + p[i]] == ma[i - p[i]]) p[i]++;
23         if(i+p[i] > mx) {
24             mx = i + p[i];//mx代表i位置向右延伸最右端的位置
25             id = i;//id记录最优mx情况下i的位置
26         }
27     }
28 }
29 int main() {
30     //freopen("in.txt","r",stdin);
31     //freopen("out.txt,"w",stdout");
32     ios_base::sync_with_stdio(0);cin.tie();
33      char s[110000];
34      while(scanf("%s",s) != EOF) {
35          int len = strlen(s);
36          Manacher(s, len);
37          int ans = 0;
38          for(int i = 0; i < 2*len+2; i++)
39              ans = max(ans, p[i] - 1);
40          printf("%d\n",ans);
41      }
42      return 0;
43 }下列这图是盗用别人的,这张图很好诠释了p[i] = mx > i ? min(p[2*id - i],mx - i) : 1;

j = 2*id - 1; p[j] 已经算出来了,又因为id向左向右延伸mx都是回文的,所以p[i] == p[j] (在满足小于 mx - i 的情况下)

				
时间: 2024-10-06 10:16:02

Manacher算法—最长回文串的相关文章

Manacher算法 最长回文串

Manacher算法O(n) 因为对于偶回文,是需要从虚轴扩充,ab,ba,所以如下: 先把原字符串处理,都加上一个标记符,比如#(特殊字符任何都可以,对于计算结果不会有影响) 1221-->#1#2#2#1# 121-->#1#2#1# 按照处理后的字符串求它的最长回文串长度m,所以原始字符串最长子回文串的长度是m/2 变量: 1:PArra[] 存放回文半径:某个位置能扩充的回文半径的长度,例如 #1#2#2#1#,2位置PArra[3] = 4 2:int PR 能够扫到的最右的回文的位

Manacher算法----最长回文子串

题目描述 给定一个字符串,求它的最长回文子串的长度. 分析与解法 最容易想到的办法是枚举所有的子串,分别判断其是否为回文.这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包含另一个短一些的子串,那么对子串的回文判断其实是不需要的.同时,奇数和偶数长度还要分别考虑. Manacher算法可以解决上述问题,并在O(n)时间复杂度内求出结果.下面我们来看一下Manacher算法. 首先,为了处理奇偶的问题,在每个字符的两边都插入一个特殊的符号,这样所有的奇数或偶数长度都转换为奇数长度.比

Manacher算法——最长回文子串(O(n))

1 public static int Manacher(String A,int n){ 2 char AA[]=A.toCharArray(); 3 char BB[]=new char[2*n+3]; 4 int k=0; 5 for(int i=1;i<=2*n+1;i=i+2){ 6 BB[i]='#'; 7 if(i+1<=2*n+1)BB[i+1]=AA[k++]; 8 } 9 BB[0]='$';//防止数组越界 10 BB[2*n+2]='&';//防止数组越界 11

LeetCode 5 Longest Palindromic Substring manacher算法,最长回文子序列,string.substr(start,len) 难度:2

https://leetcode.com/problems/longest-palindromic-substring/ manacher算法相关:http://blog.csdn.net/ywhorizen/article/details/6629268 class Solution { public: string longestPalindrome(string s) { char ch[2001];int p[2001]; ch[2*s.size()] = 0; for(int i =

hdu 3068 最长回文串 o(n) Manacher 算法

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10596    Accepted Submission(s): 3759 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多

HDU ACM 4513 吉哥系列故事——完美队形II-&gt;求最长回文串(manacher算法)

分析:该題可以通过求最长回文串的方法来解决:求最长回文串使用manacher算法,O(n)时间复杂度. 注意:while(a[i-len[i]]==a[i+len[i]] && a[i-len[i]]<=a[i-len[i]+2])这里多出的判断a[i-len[i]]<=a[i-len[i]+2]即为该題的限制从左到中保证身高不降,因在回文串的计算过程中添加了额外的字符,所以这里是i-len[i]+2而不是i-len[i]+1,以避开添加的字符. #include<ios

Manacher算法 O(n)求最长回文串

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5158    Accepted Submission(s): 1755 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

1112个人赛,最长回文串常见算法讨论

ps.此贴大部分文字与代码来自网上,我只是取长补短整理了下 S=“c a b a”  那么  S' = “a b a c”, 这样的情况下 S和 S‘的最长公共子串是aba.没有错误. 但是当 S=“abacdfgdcaba”, 那么S’ = “abacdgfdcaba”. 这样S和S‘的最长公共子串是abacd.很明显abacd并不是S的最长回文子串,它甚至连回文都不是. 现在是不是都明白为什么最长回文子串不能转化成为最长公共子串问题了.当原串S中含有一个非回文的串的反序串的时候,最长公共子串

Hdu 3294 Girls&#39; research (manacher 最长回文串)

题目链接: Hdu 3294  Girls' research 题目描述: 给出一串字符串代表暗码,暗码字符是通过明码循环移位得到的,比如给定b,就有b == a,c == b,d == c,.......,a == z. 问最长回文串所在区间,以及最长回文串所表示的明码. 解题思路: 字符串长度[1,200000],用manacher算法很轻松就搞定了. get√新技能请点击me 1 #include <cstdio> 2 #include <cstring> 3 #includ