题目链接: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. HDU 2577(DP)

    题意:要求一个字符串输入,按键盘的最少次数.有Caps Lock和Shift两种转换大小写输入的方式 思路:用dpa与dpb数组分别记录Caps Lock的开关状态,dpa表示不开,dpb表示开 代码 ...

  2. web.xml 详细介绍(转)

    web.xml 详细介绍 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧 ...

  3. moment.js 的简单应用

     moment.js :时间处理的组件 例子:moment.html <!DOCTYPE html> <html> <head> <title>mome ...

  4. 用vs2010编译和调试多个arx版本的arx项目

    翻译自dev guide<Compile and Debug Mixed-mode projects>    默认vs2010是使用ARX2014,开发AutoCAD2014使用的ARX, ...

  5. 认识zookeeper

    之前稍微看了一下Hadoop相关的技术文档,有了解到Hbase用zookeeper做分布式应用程序协调服务. 现在做的项目里,也是用zookeeper做集群和负载均衡(从类名LoadBalance看来 ...

  6. Android学习笔记(四)

    一个应用程序是有很多活动构成的,使用Intent在活动间移动. Intent分为显式和隐式两种: 1.显示Intent: 新建一个布局文件,命名为second_layout.xml,代码如下 < ...

  7. hpp头文件与h头文件的区别

    hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再将cpp加入到project中进行编译.而实现代码将直接 ...

  8. Angular SEO方案

    1.如果是java web项目,可以直接使用AngularSEO Filter. 官网地址 :http://www.angularseo.net/#about <filter> <f ...

  9. linux 平均负载 load average 的含义

      load average 的含义 平均负载(load average)是指系统的运行队列的平均利用率,也可以认为是可运行进程的平均数. 以路况为例, 单核CPU.单车道 情况如下: 0.00-1. ...

  10. 因开启SELinux导致httpd报403

    各项权限都检查过了,SELinux允许的端口也找过了.同目录下的其他文件夹是正常的,这个文件夹就抱403. 临时关闭selinux后正常.估计是没有配置运行上下文. chcon -R -t httpd ...