题目链接: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. DNA排序

    Q:DNA排序 总时间限制:1000ms内存限制:65536kB 描述 给出一系列基因序列,由A,C,G,T四种字符组成.对于每一个序列,定义其逆序对如下: 序列中任意一对字符X和Y,若Y在X的右边( ...

  2. Spring源码学习之:ClassLoader学习(1)

    转载:http://longdick.iteye.com/blog/442213 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloade ...

  3. js 日期按年月日加减

    <script> function isleapyear(year) { if(parseInt(year)%4==0 && parseInt(year)%100!=0)r ...

  4. Nginx-uri、request_uri、document_uri之间的区别

    在nginx中有几个关于uri的变量,包括$uri.$request_uri.$document_uri,下面看一下他们的区别 :$request_uri: /stat.php?id=1585378& ...

  5. Following a Select Statement Through Postgres Internals

    This is the third of a series of posts based on a presentation I did at the Barcelona Ruby Conferenc ...

  6. maven项目修改java编译版本的方式

    背景 使用 maven 3.x 安装到本地后,创建的项目一般都是基于JDK1.5版本.而目前大多数的项目已经升级到1.6或以上,尤其是Servlet3.0 已经要求Java6或以上版本的环境,往往需要 ...

  7. sqlserver2008 ,只能选C盘目录,不能选其它盘目录

    数据库sql2008安装后,无论备份或还原,只能看到C盘,手工输入路径,错误提示如下:尝试打开或创建物理文件 'D:\数据库\db.mdf' 时,CREATE FILE 遇到操作系统错误 5(拒绝访问 ...

  8. [java] java解析txt文件

    /** * 读取txt文件内容封装为map返回 * @param filePath * @return */ public static String readTxt(String filePath) ...

  9. jquery checkbox反复调用attr('checked', true/false)只有第一次生效

    /** * 全选 */ function checkAll() { $("input[name=ids]").attr("checked", true); } ...

  10. PHP入门part1

    有人说php是世界上最好的语言,那它好在哪呢. 它是开源自由的软件,能够在所有的操作平台上稳定的运行,入门比较简单.对于我这种没学过什么计算机语言的人是最好的起步点. PHP现在的含义:Hypetex ...