[hiho 01]最长回文子串、Manacher算法

题目描述

- 基础方法:枚举子串,判断是否为回文串。

- 改进:枚举中间位置,向两侧拓展。

- 再改进:利用以前的信息,使得不用每个新位置都从长度1开始拓展。

- 优化:将字符串预处理为奇数长度以避免考虑条件分支。

- 再优化:开头加入特殊字符避免考虑边界。

Manacher 算法:

id 是中心点,mx 是其边界。P[i] 表示以 i 为中心的最长回文子串的折半长度。

只要 i < mx, 以 i 为中心的回文子串就可以不必从长度1开始找,而从min{P[j], mx - i}开始(其中j为i关于id的对称点)。

当mx可以向右前进时(i + P[i] > mx),改变id和mx的值。

具体实现的代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX_SIZE 1000000
char str[2 * MAX_SIZE + 10];
int p[2 * MAX_SIZE + 10];

int main()
{
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%s", str);
        int n = strlen(str);
        for (int i = n - 1; i >= 0; i--) {
            str[2*i+2] = str[i];
            str[2*i+3] = ‘#‘;
        }
        str[0] = ‘$‘;
        str[1] = ‘#‘;
        memset(p, 0, sizeof(p));
        int id = 0, mx = 0;
        int res = 0;
        for (int i = 1; i < 2*n+4; i++) {
            p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
            while (str[i + p[i]] == str[i - p[i]]) {
                p[i]++;
            }
            res = max(res, p[i]);
            if (i + p[i] > mx)
            {
                mx = i + p[i];
                id = i;
            }
        }
        printf("%d\n", res - 1);
    }
    return 0;
}

吐槽:p数组大小没乘2,但是hiho居然报wa。白找了半天错。

Ref:http://taop.marchtea.com/01.05.html

时间: 2024-08-05 10:49:48

[hiho 01]最长回文子串、Manacher算法的相关文章

HiHo 1032 最长回文子串 (Manacher算法求解)

Manacher算法o(n)求解最长回文子串问题 非常巧妙 #include<bits/stdc++.h> using namespace std; char str[2000020],s[2000020]; int p[2000020]; int len,id,mx; void pre() //对字符串进行预处理 { len=strlen(s); str[0]='$'; str[1]='#'; for(int i=0;i<len;i++) { str[i*2+2]=s[i]; str[

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

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

hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]

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

最长回文子串 - Manacher算法

算法思想: 设有字符串s[] = "121" 第一步:通过在每个字符左右都添加一个特殊字符,把奇数长度和偶数长度的字符串都转化成奇数(例如. "121" 加上特殊字符后变成"#1#2#1" ),同时也可在开头再加一个特殊字符,以便于忽略越界问题(如上例"121"变成"$#1#2#1#"  此时开头的特殊字符$和字符串末尾的\0与此串中其他字符都不同,即可忽略越界问题),此时字符串变成 s[] = "

最长回文子串Manacher算法模板

Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 例题:HDU 3068 1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 using namespace std; 5 const int N=110005; 6 char s[N],cpy[N<<1]; 7 int rad[N&l

求最长回文子串——Manacher算法

回文串包括奇数长的和偶数长的,一般求的时候都要分情况讨论,这个算法做了个简单的处理把奇偶情况统一了.算法的基本思路是这样的,把原串每个字符中间用一个串中没出现过的字符分隔开来(统一奇偶),用一个数组p[ i ]记录以 str[ i ] 为中间字符的回文串向右能匹配的长度.先看个例子 原串:       w  a   a   b   w   s   w   f   d 新串(str):  #   w  #   a   #   a   #   b  #   w   #   s    #   w   

hihocoder1032(最长回文子串manacher算法)

题目连接:点击打开链接 解题思路: manacher算法的模板题. 完整代码: #include <algorithm> #include <iostream> #include <cstring> #include <complex> #include <cstdio> #include <string> #include <cmath> #include <queue> using namespace st

HDU3068(最长回文子串manacher算法)

题目连接:点击打开链接 解题思路: manacher算法模板题. 完整代码: #include <algorithm> #include <iostream> #include <cstring> #include <complex> #include <cstdio> #include <string> #include <cmath> #include <queue> using namespace std

5. Longest Palindromic Substring(最长回文子串 manacher 算法)

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example: Input: "babad" Output: "bab" Note: "aba" is also a valid answer. Example: Input: "cbbd" Ou