hdu5371 最长回文子串变形(Manacher算法)

http://acm.hdu.edu.cn/showproblem.php?

pid=5371

Problem Description

Hotaru Ichijou recently is addicated to math problems. Now she is playing with N-sequence.

Let‘s define N-sequence, which is composed with three parts and satisfied with the following condition:

1. the first part is the same as the thrid part,

2. the first part and the second part are symmetrical.

for example, the sequence 2,3,4,4,3,2,2,3,4 is a N-sequence, which the first part 2,3,4 is the same as the thrid part 2,3,4, the first part 2,3,4 and the second part 4,3,2 are symmetrical.

Give you n positive intergers, your task is to find the largest continuous sub-sequence, which is N-sequence.

Input

There are multiple test cases. The first line of input contains an integer T(T<=20), indicating the number of test cases.

For each test case:

the first line of input contains a positive integer N(1<=N<=100000), the length of a given sequence

the second line includes N non-negative integers ,each interger is no larger than  ,
descripting a sequence.

Output

Each case contains only one line. Each line should start with “Case #i: ”,with i implying the case number, followed by a integer, the largest length of N-sequence.

We guarantee that the sum of all answers is less than 800000.

Sample Input

1
10
2 3 4 4 3 2 2 3 4 4

Sample Output

Case #1: 9
/**
hdu5371 最长回文子串变形(Manacher算法)
题目大意:找出一个字符串能够均分为三段,第一段和第三段同样。和第二段互为回文串
解题思路:利用Manacher算出每一个位置的最长回文子串的长度,然后枚举就可以
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=210001;
int s[maxn],a[maxn];
int r[maxn],len;

void Manancher()
{
    int l=0;
    a[l++]=-2;
    a[l++]=-1;
    for(int i=0;i<len;i++)
    {
        a[l++]=s[i];
        a[l++]=-1;
    }
    a[l]=-3;
    int mx=0,id=0;
    for(int i=0;i<l;i++)
    {
        r[i]=mx>i?

min(r[2*id-i],mx-i):1;
        while(a[i+r[i]]==a[i-r[i]])r[i]++;
        if(i+r[i]>mx)
        {
            mx=i+r[i];
            id=i;
        }
        //printf("%d ",r[i]);
    }
   // printf("\n");
}

int main()
{
    int T,tt=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&len);
        for(int i=0;i<len;i++)
        {
            scanf("%d",&s[i]);
        }
        Manancher();
        int ans=0;
        for(int i=1;i<=len*2+1;i+=2)
        {
            for(int j=i+r[i]-1;j-i>ans;j-=2)
            {
                if(j-i+1<=r[j])
                {
                    ans=max(ans,j-i);
                    break;
                }
            }
        }
        printf("Case #%d: %d\n",++tt,ans/2*3);
    }
    return 0;
}
时间: 2024-10-13 11:51:04

hdu5371 最长回文子串变形(Manacher算法)的相关文章

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

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

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

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

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

求最长回文子串:Manacher算法

主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右对称的字符串,如:"abba",而最长回文子串则是字符串长度最长的回文子字符串,如"abbaca"的最长回文子串为"abba". 常规解法:显而易见采用嵌套循环的方式可以“暴力”结算出答案,其时间复杂度为O(n^2),而Manacher算法是一种更加

最长回文子串(Manacher算法)

回文字符串,想必大家不会不熟悉吧? 回文串会求的吧?暴力一遍O(n^2)很简单,但当字符长度很长时便会TLE,简单,hash+二分搞定,其复杂度约为O(nlogn), 而Manacher算法能够在线性的时间内处理出最长回文子串. 让我们来看道题:http://acm.hdu.edu.cn/showproblem.php?pid=3068 这个算法的巧妙之处,便是把奇数的回文串和偶数的回文串统一起来考虑了.这一点一直是在做回文串问题中时比较烦的地方.这个算法还有一个很好的地方就是充分利用了字符匹配

#1032 : 最长回文子串 (Manacher算法)

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

找出最长回文子串之Manacher算法

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.暴力求解. 计算字符串的最长回文字串最简单的算法就是枚举该字符串的每一个子串,并且判断这个子串是否为回文串,这个算法的时间复杂度为O(n^3)的,

最长回文子串(Manacher算法模板题)&amp;&amp;对称字符串问题

manacher:可以解决最长回文问题. 算法:1.首先,将字符串的每个字符左右加入#,并在s0位置加入*(如果字符串中本身含有这些,则换成未出现过的字符),此时字符串的长度为len+len+3,即加入了len+1个#和一个*; (比如:aba变成 *#a#b#a#) 2.得到一个p数组,该数组是基于新字符串进行的. 得到p数组 :①从1~2*len遍历字符串,即从第一个#到最后一个字符(或者说*和最后一个#不用),即要得到p[1]~p[2*len]: ②遍历的过程中,定义了两个新变量,id和m

最长回文子串问题—Manacher算法

Manacher 算法(http://www.jianshu.com/p/799bc53d4e3d) 对于一个比较长的字符串,O(n^2)的时间复杂度是难以接受的.Can we do better?先来看看解法2存在的缺陷. 1)由于回文串长度的奇偶性造成了不同性质的对称轴位置,解法2要对两种情况分别处理: 2)很多子串被重复多次访问,造成较差的时间效率. 缺陷2)可以通过这个直观的小??体现: char: a b a b a i : 0 1 2 3 4 当i==1,和i==2时,左边的子串ab