题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371

题意:把一个数字串A翻过来(abc翻过来为cba)的操作为-A,我们称A-AA这样的串为N-sequence,现在给你一个数字串,问你这个串中最长的N-sequence子串长度

解:可以想到A-A是一个回文串,-AA也是一个回文串,那么首先Manacher跑一遍求出所有回文子串

可以想到任意两个互相覆盖串中心点的回文子串都可以表示成N-sequence

然后大概有三种搞法:

1、时间复杂度O(N*logN),官方题解的方法。

  将回文子串以从长到短的顺序加到一个set中(插入值为回文子串的中心位置),插入每个串前询问,该串覆盖范围内离它最远的子串中心位置,来更新答案(因为是从长到短插入set的,所以如果后来的串覆盖了某中心,那么该中心所代表的串一定覆盖后来的串

  加了一点注释在代码里面~

2、时间复杂度O(N*logN*logN),比赛的时候写(shui)的。

  用分治+rmq乱搞了~价值不大,具体可以看代码

3、时间复杂度O(N^2)。。。吓死了,这个确实有这样子的

  有人N^2剪枝过的,有人用了姿势奇怪的线段树,目测理论复杂度O(N^2)

O(N*logN)版本:

 /*
* Problem: hdu5371 Hotaru's problem
* Author: SHJWUDP
* Created Time: 2015/8/11 星期二 12:25:41
* File Name: 1006.cpp
* State: Accepted
* Memo: Data struct
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <set> using namespace std; int N;
vector<int> arr;
namespace Manacher {
/**
* "abacd\0" -> "$#a#b#a#c#d#\0"
*/
vector<int> arr, p; int go(vector<int> & A) {
int len=A.size();
arr.resize(A.size()*+);
p.resize(A.size()*+);
for(int i=len-; i>=; i--) {
arr[i*+]=A[i];
arr[i*+]=-;
}
arr[len*+]=-;
arr[len*+]=-;
arr[]=-;
len=len*+; ///闭区间
int maxp=, id;
for(int i=; i<len-; i++) {
if(i<maxp) p[i]=min(maxp-i, p[id-(i-id)]);
else p[i]=;
while(arr[i-p[i]]==arr[i+p[i]]) p[i]++;
if(i+p[i]>maxp) {
maxp=i+p[i];
id=i;
}
} //可以打印一下p数组,观察下~
vector<pair<int, int> > tmpArr; //pair(回文串长度, 回文串中心位置)
for(int i=; i<len-; i++) {
if(arr[i]!=- || p[i]<=) continue;
tmpArr.push_back(make_pair(p[i], i));
}
sort(tmpArr.begin(), tmpArr.end(), greater<pair<int, int> >()); //按回文串长从大到小排序
set<int> S;
int res=;
for(auto & x : tmpArr) {
//找当前串左侧覆盖的回文串中心
int lim1=x.second-(x.first-); //左侧
auto it1=S.lower_bound(lim1);
if(it1!=S.end() && lim1<=(*it1) && (*it1)<x.second) {
res=max(res, (x.second-(*it1))/*);
}
//找当前串右侧覆盖的回文串中心
int lim2=x.second+(x.first-); //右侧
auto it2=S.upper_bound(x.second+(x.first-));
if(it2!=S.begin()) --it2;
if(it2!=S.end() && x.second<(*it2) && (*it2)<=lim2) {
res=max(res, ((*it2)-x.second)/*);
}
S.insert(x.second);
}
return res;
}
void print() {
for(int i=; i<(int)arr.size(); i++) {
cout<<i<<"\t\n"[i==(int)arr.size()-];
}
for(int i=; i<(int)arr.size(); i++) {
cout<<arr[i]<<"\t\n"[i==(int)arr.size()-];
}
for(int i=; i<(int)arr.size(); i++) {
cout<<p[i]<<"\t\n"[i==(int)arr.size()-];
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in", "r", stdin);
// freopen("out", "w", stdout);
#endif
int T, now=;
scanf("%d", &T);
while(T--) {
scanf("%d", &N);
arr.resize(N);
for(int i=; i<N; i++) {
scanf("%d", &arr[i]);
}
printf("Case #%d: ", ++now);
printf("%d\n", Manacher::go(arr));
}
return ;
}

O(N*logN*logN)版本:

 /*
* Problem:
* Author: SHJWUDP
* Created Time: 2015/8/11 星期二 12:25:41
* File Name: 1006.cpp
* State:
* Memo:
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm> using namespace std; const int INF=0x7f7f7f7f; const int MaxA=2e6+; struct RMQ {
int d[MaxA][];
void init(const vector<int> & A, int n) {
for(int i=; i<n; i++) d[i][]=A[i];
for(int j=; (<<j)<=n; j++) {
for(int i=; i+(<<j)-<n; i++) {
d[i][j]=max(d[i][j-], d[i+(<<(j-))][j-]);
}
}
}
int query(int L, int R) {
int k=;
while((<<(k+)) <= R-L+) k++;
return max(d[L][k], d[R-(<<k)+][k]);
}
}; int N;
vector<int> arr(MaxA);
namespace Manacher {
/**
* "abacd\0" -> "$#a#b#a#c#d#\0"
*/
vector<int> arr(MaxA), p(MaxA), tmpArr(MaxA);
RMQ rmq; int dc(int lft, int rgt, int x) {
if(lft>=rgt) return lft;
int mid=(lft+rgt)>>;
int res=-;
if(rmq.query(lft, mid)>=x) res=dc(lft, mid, x);
else if(mid+<=rgt && rmq.query(mid+, rgt)>=x) res=dc(mid+, rgt, x);
return res;
} int go(vector<int> & A) {
int len=N, lim=len*+;
for(int i=len-; i>=; i--) {
arr[i*+]=A[i];
arr[i*+]=-;
}
arr[len*+]=-;
arr[len*+]=-;
arr[]=-;
len=len*+; ///闭区间
int maxp=, id;
for(int i=; i<len-; i++) {
if(i<maxp) p[i]=min(maxp-i, p[id-(i-id)]);
else p[i]=;
while(arr[i-p[i]]==arr[i+p[i]]) p[i]++;
if(i+p[i]>maxp) {
maxp=i+p[i];
id=i;
}
} for(int i=; i<lim; i++) {
if(arr[i]!=-) {
tmpArr[i]=-INF;
} else {
tmpArr[i]=i+p[i]-;
}
// cout<<tmpArr[i]<<" \n"[i==(int)p.size()-1];
} rmq.init(tmpArr, lim);
int res=;
for(int i=; i<len-; i++) {
if(arr[i]!=- || p[i]<=) continue;
// cout<<"to "<<i<<endl;
int lft=i-(p[i]-), rgt=i-;
int tmp=dc(lft, rgt, i);
// cout<<"tmp: "<<tmp<<endl;
if(tmp!=-) res=max(res, (i-tmp+)/*);
}
return res;
}
void print() {
for(int i=; i<(int)arr.size(); i++) {
cout<<i<<"\t\n"[i==(int)arr.size()-];
}
for(int i=; i<(int)arr.size(); i++) {
cout<<arr[i]<<"\t\n"[i==(int)arr.size()-];
}
for(int i=; i<(int)arr.size(); i++) {
cout<<p[i]<<"\t\n"[i==(int)arr.size()-];
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in", "r", stdin);
// freopen("out", "w", stdout);
#endif
int T, now=;
scanf("%d", &T);
while(T--) {
scanf("%d", &N);
for(int i=; i<N; i++) {
scanf("%d", &arr[i]);
}
printf("Case #%d: ", ++now);
printf("%d\n", Manacher::go(arr));
}
return ;
}

[2015hdu多校联赛补题]hdu5371 Hotaru's problem的更多相关文章

  1. [2015hdu多校联赛补题]hdu5384 Danganronpa

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5384 题意:函数f(A, B)定义:A.B为字符串,f(A, B)为A中有多少个不同的B(ex:f(& ...

  2. [2015hdu多校联赛补题]hdu5302 Connect the Graph

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5302 题意:给你一个无向图,它的边要么是黑色要么是白色,且图上的每个点最多与两个黑边两个白边相连.现在 ...

  3. [2015hdu多校联赛补题]hdu5301 Buildings

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5301 题目大意:给你一块由1x1方格组成的矩形区域,其中有且仅有一个坏块,现在你要在上面建矩形的房子, ...

  4. [2015hdu多校联赛补题]hdu5378 Leader in Tree Land

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5378 题意:给你一棵n个结点的有根树.因为是有根树,那么每个结点可以指定以它为根的子树(后面讨论的子树 ...

  5. [2015hdu多校联赛补题]hdu5372 Segment Game

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5372 题意:进行n次操作,操作分两种,0和1,每一个0操作按出现顺序有一个编号(从1开始 0操作 0 ...

  6. [2015hdu多校联赛补题]hdu5303 Delicious Apples

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5303 题意:在一个长为L的环形路径上种着一些苹果树,告诉你苹果树的位置(题目中以0~L指示坐标)及苹果 ...

  7. [2015hdu多校联赛补题]hdu5299 Circles Game

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5299 题意: 在欧几里得平面上有n个圆,圆之间不会相交也不会相切,现在Alice和Bob玩游戏,两人轮 ...

  8. [2015hdu多校联赛补题]hdu5348 MZL's endless loop

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题意:给你一个无向图,要你将无向图的边变成有向边,使得得到的图,出度和入度差的绝对值小于等于1, ...

  9. [2015hdu多校联赛补题]hdu5324 Boring Class

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5324 题意:给你一个二维的序列,让你找出最长的第一维升第二维降的子序列(如果多个答案,输出字典序最小) ...

随机推荐

  1. linux ssh服务器

    默认配置文件在: /etc/ssh/下 有两个需要配置的文件: ssh_config    ssh_client配置文件 sshd_config  ssh服务器的配置文件 两个文件的详细介绍和配置方法 ...

  2. jQuery的ajax()、post()方法提交数组,参数[] 问题

    当用$.ajax()向后台提交参数时,如果参数中数组的话一般在后台会用List,或Integer[] 等数组对象进行接收. 比如: $.ajax({   type: "POST", ...

  3. python数据分析之pandas库的DataFrame应用一

    DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值,字符串,布尔型).DateFrame既有行索引也有列索引,可以被看作为由Series组成的字典. 构建Dat ...

  4. SpringMVC学习系列(6) 之 数据验证

    在系列(4).(5)中我们展示了如何绑定数据,绑定完数据之后如何确保我们得到的数据的正确性?这就是我们本篇要说的内容 —> 数据验证. 这里我们采用Hibernate-validator来进行验 ...

  5. LINUX yum用法

    1.确保RHEL5中已经安装了yum [root@lvs-master ~]# rpm -qa |grep yumyum-metadata-parser-1.1.2-3.el5yum-updatesd ...

  6. python学习-day20、装饰器【图片缺失可看】印象笔记博客备份

    前言: 装饰器用于装饰某些函数或者方法,或者类.可以在函数执行之前或者执行之后,执行一些自定义的操作. 1.定义:装饰器就是一个函数,为新定义的函数.把原函数嵌套到新函数里面.以后就可以在执行新函数的 ...

  7. shell script练习

    执行脚本的几种方式: 1. sh a.sh 或者  bash a.sh  调用的是 /bin/bash 进程执行的,所以脚本不需要执行权限. 2. 直接使用绝对路径执行, /home/script/a ...

  8. bootstrap-面板、modal

    面板: <!-- panel 面板 panel-heading 面板头部 panel-title 面板标题样式 panel-body 面板内容 --> <div class=&quo ...

  9. [ActionScript 3.0] AS3.0 对象在矩形范围随机运动

    package com.views { import flash.display.Bitmap; import flash.display.MovieClip; import flash.displa ...

  10. javascript里for循环的一些事情

    今天在给一个学妹调她的代码BUG时,她的问题就是在一个for循环里不清楚流程的具体流向,所以导致了页面怎么调都是有问题,嗯确实你如果不清楚语句流向很轻易就会出问题,所以说for循环不会用或者说用的不恰 ...