码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru's problem(manacher+二分/枚举)

时间:2015-08-11 23:35:47      阅读:464      评论:0      收藏:0      [点我收藏+]

标签:枚举   字符串   manacher   

HDU 5371

题意:

定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称。
现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度。

思路:

来自官方题解:修正了一些题解错别字(误

先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中

要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样。 因为我们已经记录下来以第i个点为中心的回文串长度, 那么问题可以转化成,相距x的两个数a[i],a[i+x],满足p[i]/2>=x 并且 p[i+x]/2>=x,要求x尽量大

这可以用一个set维护,一开始集合为空,依次取出p数组中最大的元素,将其下标放入set中,每取出一个元素,在该集合中二分查找比i+p[i]/2小,但最大的元素,更新ans。 然后查找集合中比i-p[i]/2大,但最小的元素,更新ans。

答案就是3*ans

嗯~其实不用二分暴力扫下也能水过去

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const int maxn = 100000 + 5;
int p[2*maxn];
int s[maxn];
int s1[2*maxn];
int n;
void init(){
    cls(s1);
    s1[0] = -1;
    s1[1] = -2;
    int k = 2;
    for(int i = 0 ; i < n ; i++){
        s1[k++] = s[i];
        s1[k++] = -2;
    }
}

void manacher(){
    int mx = 0 , id = 0;
    p[0] = 0;
    for(int i = 0 ; i < 2*n+1 ; i++){
        if(mx > i) p[i] = min(p[2*id-i] , mx-i);
        else p[i] = 1;
        while(s1[i-p[i]] == s1[i+p[i]]) p[i]++;
        if(mx < p[i]+i){
            mx = p[i] + i;
            id = i;
        }
    }
}

int solve(){
    int ans = 0;  
    for(int i = 1; i < n*2 + 1 ; i += 2)
        if((p[i] - 1) / 2 > ans){
            for(int j = i + p[i] - 1 ; ; j -= 2){  
                if(p[j] >= j-i){  
                    ans = (j-i) / 2;  
                    break;
                } 
                if((j-i)/2 <= ans)  break;  
            }  
        } 
    return 3*ans; 
}
int main(){
  //freopen("input.txt","r",stdin);
    int t; cin >> t ; int kase = 1;
    while(t--){
        cls(s);cls(p);cls(s1);
        cin >> n;
        for(int i = 0 ; i < n ; i++){
             scanf("%d",s+i);
        }
        init();
        manacher();
        printf("Case #%d: %d\n",kase++,solve());
    }
    return 0;
}

版权声明:博主表示授权一切转载:)

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru's problem(manacher+二分/枚举)

标签:枚举   字符串   manacher   

原文地址:http://blog.csdn.net/qq_15714857/article/details/47427439

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!