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

 1 #include <map>
 2 #include <set>
 3 #include <list>
 4 #include <stack>
 5 #include <queue>
 6 #include <cmath>
 7 #include <ctime>
 8 #include <cstdio>
 9 #include <vector>
10 #include <cstdlib>
11 #include <complex>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15
16 #define REP(i,N) for (int i = 0;i < (N);i++)
17 #define REP_1(i,N) for (int i = 1;i < (N);i++)
18 #define REP_2(i,be,en) for (int i = (be);i < (en);i++)
19 #define DWN(i,N) for (int i = (N);i >= 0;i--)
20 #define DWN_1(i,N) for (int i = (N);i >= 1;i--)
21 #define DWN_2(i,en,be) for (int i = (en);i >= (be);i--)
22 #define INF 0x3f3f3f3f
23 #define MAXN 1000100
24 #define FR(N) freopen((N),"r",stdin)
25 #define FW(N) freopen((N),"w",stdout)
26 #define GETS(ch) fgets((ch),MAXN,stdin);
27 using namespace std;
28
29 typedef long long LL;
30 typedef map<string,int> MINT;
31 typedef vector<int> VINT;
32
33 const int M = 110010*2;
34 char str[M];//start from index 1
35 int p[M];
36 char s[M];
37 int n;
38 void checkmax(int &ans,int b){
39     if(b>ans) ans=b;
40 }
41 inline int min(int a,int b){
42     return a<b?a:b;
43 }
44 void kp(){
45     int i;
46     int mx = 0;
47     int id;
48     REP_1(i,n) {
49         if( mx > i )
50             p[i] = min( p[2*id-i], p[id]+id-i );
51         else
52             p[i] = 1;
53         for(; str[i+p[i]] == str[i-p[i]]; p[i]++) ;
54         if( p[i] + i > mx ) {
55             mx = p[i] + i;
56             id = i;
57         }
58     }
59 }
60 void pre() {
61     int i,j,k;
62     n = strlen(s);
63     str[0] = ‘$‘;
64     str[1] = ‘#‘;
65     REP(i,n) {
66         str[i*2 + 2] = s[i];
67         str[i*2 + 3] = ‘#‘;
68     }
69     n = n*2 + 2;
70     str[n] = 0;
71 }
72
73 void pt() {
74     int i;
75     int ans = 0;
76     REP(i,n)
77         checkmax(ans, p[i]);
78     printf("%d\n", ans-1);
79 }
80
81 int main() {
82     //FR("1.txt");
83     int _=0;
84     int N;
85     cin >> N;
86     while( N-- ) {
87         scanf("%s", s);
88         pre();
89         kp();
90         pt();
91     }
92     return 0;
93 }
时间: 2024-08-07 08:38:07

manacher 算法 O(n)最长回文子串的相关文章

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

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

hdu 3068 Manacher算法 O(n)回文子串算法

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3068 关于算法的教程  推荐这个:http://blog.csdn.net/ggggiqnypgjg/article/details/6645824    注意:我推荐的这篇博客里说的那个代码有bug,我觉得没问题,而是博主在用的时候写错了,博主举得反例我都过了 而且hdu 3068也过了 最开始是用的后缀数组,2000ms+ 果断超时............... 看过一遍很快就学会这个算法了:然后A

【数据结构与算法】动态规划——最长回文子串

最长回文子串 LeetCode:最长回文子串 题目描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案. 思想: 动态规划,用boolean[][] dp记录每一对字符是否相等: 双循环遍历所有子串情况,每次遍历时,当前子串首尾相等且内层-1字符串dp值为true,则记录dp值为true:全部遍历完,取最长,即为最

算法进阶之manacher算法 (求最长回文)

前几天bestcode做到一道字符串的题目,需要O(n)的回文,正好看到网上的manacher算法,于是来学习一发 进入正题: manacher算法 用法:一般用于求一个字符串的最大回文,操作过程中会记录以每个点为中心的回文半径,可用来进行其他操作 时间复杂度:O(n) 空间复杂度:记录字符串2*n,半径数组2*n 内容: 记p[i]为以i为中心的回文半径(aba中以b为中心的回文半径为2,那么如果是偶数个数的回文呢,比如abba?这里先讨论奇数,偶数后面再说,简单说就是用字符填充变成奇数) 因

【最长回文子串】HDU3068最长回文【Manacher算法】

一张图领悟Manacher算法,计算字符串最长回文子串 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S 两组case之间由空行隔开(该空行不用处理)

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

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

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

题目描述 - 基础方法:枚举子串,判断是否为回文串. - 改进:枚举中间位置,向两侧拓展. - 再改进:利用以前的信息,使得不用每个新位置都从长度1开始拓展. - 优化:将字符串预处理为奇数长度以避免考虑条件分支. - 再优化:开头加入特殊字符避免考虑边界. Manacher 算法: id 是中心点,mx 是其边界.P[i] 表示以 i 为中心的最长回文子串的折半长度. 只要 i < mx, 以 i 为中心的回文子串就可以不必从长度1开始找,而从min{P[j], mx - i}开始(其中j为i

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

Manacher是一个可以在O(n)的时间内求出一个长度为n的字符串的算法. 以为回文子串有偶数长度,也有奇数长度,分别处理会很不方便. 所以在每两个字符中间插入一个无关字符,如‘#’,这样所有的回文子串都变为奇数长度. 两端在添加不同的无关字符防止匹配时越界. 如: abba 变成 $#a#b#b#a#& 预处理代码: void Prepare() { l = strlen(Str); S[0] = '$'; for (int i = 0; i <= l - 1; i++) { S[(i

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

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

[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