题目链接: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. [转]STL中vector转数组(实际是数组的指针)

    感谢:http://topic.csdn.net/t/20050429/20/3976956.html 感谢:http://yzyanchao.blogbus.com/logs/47796444.ht ...

  2. 面试题一 链表中倒数第k个结点

    void findLastK(LinkedNode head, int k, int n){ if (head == NULL || k == 0) return; LinkedNode t1 = h ...

  3. centos网卡eth1变成eth0修改方法

    centos网卡eth1变成eth0修改方法 2013年03月29日 ⁄ Linux基础 ⁄ 共 406字 ⁄ 暂无评论 ⁄ 被围观 8,266 views+ 虚拟化中,从模板克隆出来的虚拟机网卡都会 ...

  4. LINQ查询操作符之Select、Where、OrderBy、OrderByDescending、GroupBy、Join、GroupJoin及其对应的查询语法

    介绍    ·Select - Select选择:延迟    ·Where - Where查询:延迟    ·OrderBy - 按指定表达式对集合正序排序:延迟    ·OrderByDescend ...

  5. Android Programing 学习笔记(一)

    最近学习android 开发,拜读android programing,一步一步学习.囫囵吞枣,现已看到第十八章.今天把最近的学习过程中学到的一些内容进行一下总结. 一:Fragment 和 Acti ...

  6. linux下生成rsa密钥的方法

    首先生成密钥,用命令ssh-keygen –t rsa 运行后可以一直空格,生成密钥,id_rsa和id_rsa.pub文件 ,默认放在/root/.ssh/下,.ssh文件是隐藏的,要显示隐藏文件才 ...

  7. zookeeper系列之通信模型(转)

    本文的主题就是讲解Zookeeper通信模型,本节将通过一个概要图来说明Zookeeper的通信模型. Zookeeper的通信架构 在Zookeeper整个系统中,有3中角色的服务,client.F ...

  8. 安装Yii框架时init.bat闪退的处理方法

    已经开启了php_openssl扩展还是会闪退 1.右击'计算机'-'属性'-'高级系统属性'-'环境变量(最下边)': 2.在'系统变量'里找到'path',双击,出现'编辑系统变量',在'变量值' ...

  9. css如何实现多行文本时,内容溢出,出现省略号

    一:单行文本出现省略号: .oneLine{ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; width: 100px; ...

  10. for语句

    一.for语句的格式格式1:for (控制变量初始化表达式;条件表达式;增量表达式)  语句1; 格式2:for (控制变量初始化表达式;条件表达式;增量表达式){ 语句1;  语句2;  -} 注意 ...