manacher算法专题

一、模板

算法解析:http://www.felix021.com/blog/read.php?2040

 1 *主要用来解决一个字符串中最长回文串的长度,在O(n)时间内,线性复杂度下,求出以每个字符串为中心的最长回文,奇数回文跟偶数回文一起考虑了
 2 S  $ # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #
 3 P   1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
 4
 5 最后所求的值就是max(P[i]-1)
 6
 7 //输入,并处理得到字符串s,s[0]=$
 8 void getp()
 9 {
10     int p[1000], mx = 0, id = 0;
11     memset(p, 0, sizeof(p));
12     for (i = 1; s[i] != ‘\0‘; i++)
13     {
14         p[i] = mx>i ? min(p[2*id-i], mx-i) : 1;
15         while (s[i + p[i]] == s[i - p[i]]) p[i]++;
16         if (i + p[i] > mx)
17         {
18             mx = i + p[i];
19             id = i;
20         }
21     }
22 }

二、题目

1、【HDU 4513】吉哥系列故事――完美队形II

题意:输入n(1 <= n <= 100000)个人的身高hi(50 <= hi <= 250),从这些人中连续挑出k个人,这k个人【身高是左右对称的,如果是k是奇数,那么中间那个人的身高任意】&&【从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]】,求k的最大值。

解题思路:一般的manacher添加的是’#’,但是本题左半边的身高不递减,所以添加的应该是(h[i]+h[i+1])/2,注意细节。处理后的第奇数个身高是添加上去的,第偶数个身高是一开始输入的,当i-p[i]是奇数时,无论hh[i-p[i]]与hh[i+p[i]]是否相等,p[i]都应该+1。

比如:h[] = 80 60 70 60 90 50 ==> hh[] = -1 65 80 70 60 65 70 65 60 75 90 70 50 65【有颜色的是原串】,以70为中心时,p[6]=4而不是3

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <string>
 6 using namespace std;
 7 const int N=2*1e5+10;
 8 int h[N], hh[N];
 9 int t, n;
10 int p[N], lenhh;
11 void getp()
12 {
13     int mx = 0, id = 0;
14     memset(p, 0, sizeof(p));
15     for (int i = 1; i<lenhh; i++)
16     {
17         p[i] = mx>i ? min(p[2*id-i], mx-i) : 1;
18         while(hh[i + p[i]] == hh[i - p[i]] && hh[i-p[i]]<=hh[i-p[i]+1]) p[i]++;
19         if((i-p[i])%2) p[i]++;
20         if (i + p[i] > mx)
21         {
22             mx = i + p[i];
23             id = i;
24         }
25     }
26 }
27 int main(){
28     scanf("%d", &t);
29     while(t--){
30         scanf("%d", &n);
31         for(int i=1; i<=n; i++){
32             scanf("%d", &h[i]);
33         }
34         h[0]=h[n], h[n+1]=h[1];
35         lenhh=2;
36         hh[1]=(h[0]+h[1])/2, hh[0]=-1;
37         for(int i=1; i<=n; i++){
38             hh[lenhh++]=h[i];
39             hh[lenhh++]=(h[i]+h[i+1])/2;
40         }
41 //        for(int i=0; i<lenhh; i++) cout<<hh[i]<<" ";
42 //        cout<<endl;
43         getp();
44         int maxn=0;
45 //        for(int i=0; i<lenhh; i++) cout<<p[i]<<" ";
46 //        cout<<endl;
47         for(int i=1; i<lenhh; i++) maxn = max(maxn, p[i]-1);
48         printf("%d\n", maxn);
49     }
50     return 0;
51 }

时间: 2024-10-06 08:32:34

manacher算法专题的相关文章

HDU 3068 最长回文 (manacher算法)

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

最长回文---hdu3068 (回文串 manacher 算法模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意很清楚:就是求一个串s的子串中最长回文串的长度:这类题用到了manacher算法 manacher算法(复制大神的解释): 定义数组p[i]表示以i为中心的(包含i这个字符)回文串半径长 将字符串s从前扫到后for(int i=0;i<strlen(s);++i)来计算p[i],则最大的p[i]就是最长回文串长度,则问题是如何去求p[i]? 由于s是从前扫到后的,所以需要计算p[i]时一定

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 =

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

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

浅谈Manacher算法与扩展KMP之间的联系

首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解,网上解法颇多,时间复杂度也不尽相同,这里列述几种常见的解法. 解法一 通过枚举S的子串,然后判断该子串是否为回文,由于S的子串个数大约为,加上每次判断需要的时间,所以总的时间复杂度为,空间复杂度为. bool check(string &S, int left, int right) { while (left < right && S[left]

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

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

hdu-3068 最长回文 【Manacher算法】

Manacher算法学习资料:http://blog.csdn.net/dyx404514/article/details/42061017 最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9282    Accepted Submission(s): 3194 Problem Description 给出一个只由小写英文字符

hdu-3613 Best Reward (manacher算法)

Best Reward 题目链接 Description After an uphill battle, General Li won a great victory. Now the head of state decide to reward him with honor and treasures for his great exploit. One of these treasures is a necklace made up of 26 different kinds of gems

Manacher算法 , 实例 详解 . NYOJ 最长回文

Manacher 算法 定义数组 p[i]表示以i为中心