试题描述

输入一个字符串S,回答Q次问题,给你l,r,输出子序列[l,r]的最长连续回文串长度。

输入

第一行为一个字符串S。

第二行为一个正整数Q。

接下来Q行每行为l,r。

输出

对于每个询问,输出答案。

输入示例

aababababaabababaaa

4

1 3

2 6

1 10

2 7

输出示例

2

5

9

5

其他说明

1<=|S|,Q<=100000

1<=l<=r<=|S|

由于求区间的最长回文串长度,这显然不是很容易的事情,我们考虑用分块来维护答案。

我们每SIZE个元素分成一块,询问时要得到大块之间的答案以及小部分贡献的答案。

前者我们可以预处理出来(马拉车或PAM),时间复杂度O(N^2/SIZE)。

后者我们可以用PAM,当回文串的一段在小段时,肯定是左端在左小段,右端在右小段。两者是对称的,我们开始考虑怎么求回文串右端在右小段的答案。

预处理每个位置在PAM上的节点,但这可能超过询问边界,所以我们要不停地沿失配边向上走,当节点的的长度<=限制长度时返回。

如果暴力的话虽然对于随机数据表现很好,但会被特殊数据卡。因此我们可以用倍增来做,那么这一部分的时间复杂度为O(Q*SIZE*logSIZE)。

总时间复杂度为O(N^2/SIZE+Q*SIZE*logSIZE),实测SIZE取[150,200]即可。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<stack>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
char ch[maxn];
int lpos[maxn],rpos[maxn],nowret;
struct PAM {
int last,cnt,to[maxn][],l[maxn],fa[maxn];
int first[maxn],next[maxn],To[maxn],anc[maxn][],e;
void init() {
memset(to,,sizeof(to));
memset(l,,sizeof(l));
memset(fa,,sizeof(fa));
memset(first,,sizeof(first));
cnt=fa[]=;l[]=-;last=e=;
}
void extend(int c,int n,int id) {
int p=last;
while(ch[n]!=ch[n-l[p]-]) p=fa[p];
if(!to[p][c]) {
int np=++cnt,k=fa[p];l[np]=l[p]+;
while(ch[n]!=ch[n-l[k]-]) k=fa[k];
fa[np]=to[k][c];to[p][c]=np;
}
nowret=max(nowret,l[last=to[p][c]]);
if(id>) lpos[id]=last;
else rpos[-id]=last;
}
stack<int> S;
void dfs(int x) {
S.push(x);
while(!S.empty()) {
x=S.top();S.pop();
anc[x][]=fa[x];
rep(i,,) anc[x][i]=anc[anc[x][i-]][i-];
ren S.push(To[i]);
}
}
void AddEdge(int u,int v) {
To[++e]=v;next[e]=first[u];first[u]=e;
}
void build() {
fa[]=;rep(i,,cnt) if(i!=) AddEdge(fa[i],i);
dfs();
}
int solve(int x,int limit) {
if(l[x]<=limit) return l[x];
for(int i=;i>=;i--) if(l[anc[x][i]]>limit) x=anc[x][i];
return l[fa[x]];
}
}sol1,sol2;
int n,SIZE;
int ans[][],bl[maxn],st[maxn],en[maxn];
int main() {
scanf("%s",ch+);n=strlen(ch+);SIZE=;
rep(i,,n) {
bl[i]=(i-)/SIZE+;
en[bl[i]]=i;
if(!st[bl[i]]) st[bl[i]]=i;
}
rep(i,,bl[n]) {
sol1.init();nowret=;
char c=ch[st[i]-];ch[st[i]-]='~';
rep(j,st[i],n) {
sol1.extend(ch[j]-'a',j,);
ans[i][bl[j]]=max(ans[i][bl[j]],nowret);
}
ch[st[i]-]=c;
}
sol1.init();sol2.init();
rep(i,,n) sol1.extend(ch[i]-'a',i,i);
reverse(ch+,ch+n+);
rep(i,,n) sol2.extend(ch[i]-'a',i,-(n-i+));
sol1.build();sol2.build();
int m=read();
while(m--) {
int l=read(),r=read(),ret=;
if(bl[l]+>=bl[r]) rep(i,l,r) ret=max(ret,sol1.solve(lpos[i],i-l+));
else {
ret=ans[bl[l]+][bl[r]-];
rep(i,l,en[bl[l]]) ret=max(ret,sol2.solve(rpos[i],r-i+));
rep(i,st[bl[r]],r) ret=max(ret,sol1.solve(lpos[i],i-l+));
}
printf("%d\n",ret);
}
return ;
}

COJ975 WZJ的数据结构(负二十五)的更多相关文章

  1. 策略模式 Strategy 政策Policy 行为型 设计模式(二十五)

    策略模式 Strategy   与策略相关的常见词汇有:营销策略.折扣策略.教学策略.记忆策略.学习策略.... “策略”意味着分情况讨论,而不是一概而论 面对不同年龄段的人,面对不同的商品,必然将会 ...

  2. Bootstrap <基础二十五>警告(Alerts)

    警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警告(Alerts)向用户提供了一种定义消息样式的方式.它们为典型的用户操作提供了上下文信息反馈. 您可以为警告框添加一个 ...

  3. VMware vSphere 服务器虚拟化之二十五 桌面虚拟化之终端服务池

    VMware vSphere 服务器虚拟化之二十五 桌面虚拟化之终端服务池 终端服务池是指由一台或多台微软终端服务器提供服务的桌面源组成的池.终端服务器桌面源可交付多个桌面.它具有以下特征: 1.终端 ...

  4. WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇]

    原文:WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇] 在[WS标准篇]中我花了很大的篇幅介绍了WS-MEX以及与它相关的WS规范:WS-Policy.WS-Tra ...

  5. Bootstrap入门(二十五)JS插件2:过渡效果

    Bootstrap入门(二十五)JS插件2:过渡效果 对于简单的过渡效果,只需将 transition.js 和其它 JS 文件一起引入即可.如果你使用的是编译(或压缩)版的bootstrap.js  ...

  6. JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

    JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...

  7. JAVA之旅(二十五)——文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine

    JAVA之旅(二十五)--文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine 我们继续IO上个篇 ...

  8. Java进阶(二十五)Java连接mysql数据库(底层实现)

    Java进阶(二十五)Java连接mysql数据库(底层实现) 前言 很长时间没有系统的使用java做项目了.现在需要使用java完成一个实验,其中涉及到java连接数据库.让自己来写,记忆中已无从搜 ...

  9. 二十五. Python基础(25)--模块和包

    二十五. Python基础(25)--模块和包 ● 知识框架   ● 模块的属性__name__ # my_module.py   def fun1():     print("Hello& ...

随机推荐

  1. MySQL建立索引的注意事项

    对于大数据量的表格,尤其是百万行以上的数据表,一定要对其建立索引,否则查询速度极慢.(参考后面的测试结果)建立索引时需注意: MySQL的索引有两种:单列索引(即在某一列上建索引).多列组合索引(即在 ...

  2. poj 1664

    http://poj.org/problem?id=1664 题目是中文的,一个递归的题目 把每一次的苹果分为两类 Ⅰ:所以盘子都放一个,然后其他的在随便放: Ⅱ:有一个盘子没有放苹果: 这样下去的话 ...

  3. js 基本介绍

    ecma  对象 三个包类型  String   ParseInt  ParseDouble instanceof typeof Math  对象 Array Date RegExp -- bom对象 ...

  4. Python网络编程(4)——异步编程select & epoll

    在SocketServer模块的学习中,我们了解了多线程和多进程简单Server的实现,使用多线程.多进程技术的服务端为每一个新的client连接创建一个新的进/线程,当client数量较多时,这种技 ...

  5. FZU 2140 Forever 0.5 (几何构造)

    Forever 0.5 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit  ...

  6. July 20th, Week 30th Wednesday, 2016

    Learn from yesterday, live for today, and hope for tomorrow. 借鉴昨天,活着当下,憧憬未来. Yesterday is the past, ...

  7. sublime text3083 破解 插件汉化

      sublime text  注册码 1. Sublime Text 2.x 版本 —– BEGIN LICENSE —– Andrew Weber Single User License EA7E ...

  8. ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(二) 实现聊天室连接

    上一篇已经简单介绍了layim WebUI即时通讯组件和获取数据的后台方法.现在要讨论的是SingalR的内容,之前都是直接贴代码.那么在贴代码之前先分析一下业务模型,顺便简单讲一下SingalR里的 ...

  9. 学习hadoop,搭建hadoop遇到一些特殊问题

    我执行下面步骤: 1.  动态增加DataNode节点和TaskTracker节点 以host9为例 在host9上执行: 指定主机名 vi  /etc/hostname 指定主机名到IP地址的映射 ...

  10. java 基本数据类型

    long 是长整型,在怎么长本身也是整型,12.10的整形部分是12,当然结果是12, byte: 八位整数 -128——127,可用来节省内存的使用.short: 16位整数 -32768——32, ...