试题描述

输入一个字符串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. 07 DAY 1

    壮烈的一天... 第一题 本意是水题,然后写了块状数组模拟,最后发现算法错了... 然后其实快排一遍扫一遍完事... 100分 #include <cstdio> #include < ...

  2. php中global与$GLOBALS的用法及区别

    php中global 与 $GLOBALS[""] 差别 原本觉得global和$GLOBALS除了写法不一样觉得,其他都一样,可是在实际利用中发现2者的差别还是很大的! 先看下面 ...

  3. selenium webdriver的各种driver

    selenium官方加上第三方宣布支持的驱动有很多种:除了PC端的浏览器之外,还支持iphone.Android的driver:大概记录一下selenium支持的各种driver的用途与说明. sel ...

  4. 应用 JD-Eclipse 插件实现 RFT 中 .class 文件的反向编译

    概述 反编译是一个将目标代码转换成源代码的过程.而目标代码是一种用语言表示的代码 , 这种语言能通过实机或虚拟机直接执行.文本所要介绍的 JD-Eclipse 是一款反编译的开源软件,它是应用于 Ec ...

  5. Java for LeetCode 188 Best Time to Buy and Sell Stock IV【HARD】

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  6. cocos2dx创建sprite的多种方法

    方法一 最常用,也是最简单的一种方法 CCSprite *bg=CCSprite::create(,,,)); bg->setAnchorPoint(ccp(,)); bg->setPos ...

  7. Java查询网址

    Java在线帮助文档: http://docs.oracle.com/javase/8/docs/technotes/guides/desc_jdk_structure.html Java小知识讲解: ...

  8. CodeIgniter - 数据库的增删改查

    数据库操作无非是CRUD,用非装逼的语言来说就是增删改查.也许这一节会讲的很泛泛,或者很多人看不懂,没关系,大致的看看,知道是这么回事就好,继续往后看,后面会讲实例,这些枯燥而又抽象的东西可以先跳过, ...

  9. 面向服务的体系结构(SOA)——(3)关于BPM

    什么是BPM 很多情况下企业当中所提供的服务不是由一个分布式业务流程就可以完成的,整个服务的提供需要多个分布式流程有机的组合,于是BPM就应运而生了.要将现有的服务通过配置.编排(关于配置与编排的区别 ...

  10. Java hour5

    有句名言,叫做10000小时成为某一个领域的专家.姑且不辩论这句话是否正确,让我们到达10000小时的时候再回头来看吧. 本文作者Java 现经验约为4 Hour,请各位不吝赐教. Hour5 神一样 ...