Manarcher 求 字符串 的最长回文子串 【记录】

声明:这里只写出了实现过程。想学习Manacher的可以看下这里给出的实现过程,算法涉及的一些原理推荐个博客。

感觉讲的很细

引子:给定一个字符串s,让你求出最长的回文子串的长度。

算法大致实现过程:

一:为了排除回文字符串长度奇或偶的影响。先在每两个字符之间插入一个原字符串没有出现过的字符(这里就用#)构成新串str。设p[i] 为以str[i]字符为中心的回文字符串的最大半径。则新串中以str[i]为中心的回文串长度为p[i]-1。

二:字符串从前到后求p[]数组。(不要问为什么从前到后)

三:枚举所有p[i]值,更新最大值。

Manacher精华——求p[]数组。首先我们在求p[i]时,已经求出前面的p[j]值(0<=j<=i-1)

求p[i]的准备:

用mx记录 max{ k+p[ k ] } (0<=k<=i-1) ——前面所有回文字符串
能覆盖到的最右边的位置

用id记录mx取最大值时的k ——前面所有回文字符串中
能覆盖到最右边位置 的那个以字符str[id]为中心的回文串。

(1)根据前面的p[]求p[i]

一,mx > i ——以str[id]为中心的回文字符串把字符str[i]覆盖到了。

这个情况下我们可以得到 :p[ i ]= min( p[2*id - i ], mx - i )。(为什么?请看我推荐的博客)

二,mx <= i ——以str[id]为中心的回文字符串以字符str[i]结尾或者没有覆盖到字符str[i]。

这种情况下p[i] = 1,因为回文串只有它自己。(为什么?请看我推荐的博客)

(2)当然上面的处理还是不够的,因为处理过后得到的p[i]并不一定是我们所想要的最优的回文串半径。

(为什么?请看我推荐的博客)

后续处理很好理解的。

while(str[ i + p[i] ] == str[ i - p[i] ]) p[i]++;//向左右继续延伸 直到不能延伸为止

(3)每次求出p[i]后,可以先求出计算p[i+1]要用到的id。

代码实现:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 110100
using namespace std;
char s[MAXN];//原串
int str[MAXN*2];//新串 注意数组大小
int p[MAXN*2];
void Manacher(char *T)
{
    int len = strlen(T);
    int l = 0;
    str[l++] = '@';//防止越界
    str[l++] = '#';
    for(int i = 0; i < len; i++)
    {
        str[l++] = T[i];
        str[l++] = '#';
    }
    str[l] = 0;
    int mx = 0, id = 0;
    int ans = 0;
    for(int i = 0; i < l; i++)
    {
        if(mx > i)//2*id-i 为 i关于id的对称点
            p[i] = min(p[2*id - i], mx-i);
        else
            p[i] = 1;
        //左右延伸
        while(str[i+p[i]] == str[i-p[i]]) p[i]++;
        if(i + p[i] > mx)//找计算p[i+1]用到的id
        {
            mx = i + p[i];
            id = i;
        }
        ans = max(p[i]-1, ans);
    }
    printf("%d\n", ans);
}
int main()
{
    while(scanf("%s", s) != EOF)
    {
        Manacher(s);//求字符串s的 最长回文子串长度
    }
    return 0;
}

本人数据结构很渣,有错误的地方欢迎指正。 (⊙o⊙)

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-20 11:47:24

Manarcher 求 字符串 的最长回文子串 【记录】的相关文章

hiho#1032 : 最长回文子串 (manacher算法O(n)时间求字符串的最长回文子串 )

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:"小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?" 小Ho奇怪的问道:"什么叫做最长回文子串呢?" 小Hi回答道:"一个字符串中连续的一

【回文字符串】 最长回文子串O(N) Manacher算法

原理讲的清晰:Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串 注意: ①动态生命P[]和newStr数组后,不要忘记delete[] //其实这是基本的编码习惯 ②最终返回结果是P[i]-1 下面是自己写的Manacher函数 int manacher(char *src){ int srcLen=strlen(src); int len=2*srcLen+2; char *newStr=new char[len];//还是+3??要不要给\0留个位置??不用 i

计算字符串的最长回文子串 :Manacher算法介绍

在介绍算法之前,首先介绍一下什么是回文串,所谓回文串,简单来说就是正着读和反着读都是一样的字符串,比如abba,noon等等,一个字符串的最长回文子串即为这个字符串的子串中,是回文串的最长的那个. 计 算字符串的最长回文字串最简单的算法就是枚举该字符串的每一个子串,并且判断这个子串是否为回文串,这个算法的时间复杂度为O(n^3)的,显然无法令人 满意,稍微优化的一个算法是枚举回文串的中点,这里要分为两种情况,一种是回文串长度是奇数的情况,另一种是回文串长度是偶数的情况,枚举中点再判断是否 是回文

(字符串) Manacher 最长回文子串。

最长回文子串就是一个字符串的一个子串,他从左往右读和从右往左读是一样的. 可以用 Manacher 算法来求,他的复杂度是 O(n) . 可以看这篇文章 http://blog.csdn.net/ywhorizen/article/details/6629268 但是其中应该有一个错误(纠结了我一天...) 就是 这一句,文章里面是说当 Mx-i <= Mp[j] 的时候就要用到,因为后面的还没比较. 但是如图,蓝色的部分是相等的,如果红色的等于蓝色的话,那么Mx就不可能是这个值,所以红色的一定

LeetCode之“字符串”:最长回文子串

题目要求: 给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串.例如,给出字符串 "abcdzdcab",它的最长回文子串为 "cdzdc". 解答: 这个题目的一个简单的解法就是对字符串中的每一个字符,同时向其两边延展,以找到最长回文子串.这种方法是可以的,但要处理回文子串长度为奇数和偶数的两种情况是比较麻烦的.如下图的几个字符串: “a” "aa" "aaa" "

求给定字符串中最长回文子串

5. Longest Palindromic Substring 这个是在本机测试,然后一次点亮的,嘻嘻 1 char* longestPalindrome(char* s) { 2 char *p = s; /* first char */ 3 char *left, *right; /* store the pointer of longest palindrome string */ 4 int max = 0; /* store max length */ 5 while(*p != '

转载:LeetCode:5Longest Palindromic Substring 最长回文子串

本文转自:http://www.cnblogs.com/TenosDoIt/p/3675788.html 题目链接 Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 求字符串的最长回文子串 算法1:暴

[LeetCode] 5. Longest Palindromic Substring 最长回文子串

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 最长回文子串Longest palindromic substring, 最长回文子串或最长对称因子问题是在一个字符串中查找一个最长连续子串,这个子串

[hdu3068 最长回文]Manacher算法,O(N)求最长回文子串

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意:求一个字符串的最长回文子串 思路: 枚举子串的两个端点,根据回文串的定义来判断其是否是回文串并更新答案,复杂度O(N3). 枚举回文串的对称轴i,以及回文半径r,由i和r可确定一个子串,然后暴力判断即可.复杂度O(N2). 在上一步的基础上,改进判断子串是否是回文串的算法.记fi(r)=(bool)以i为对称轴半径为r的子串是回文串,fi(r)的值域为{0, 1},显然fi(r)是关于r