Description

  火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,
我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,
火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串
,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程
中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,
如果求出了LCQ函数的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速
算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地说
,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此
复杂的问题中,火星人是否还能够做到很快地求取LCQ函数的值。

Input

  第一行给出初始的字符串。第二行是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操
作有3种,如下所示
  1、询问。语法:Qxy,x,y均为正整数。功能:计算LCQ(x,y)限制:1<=x,y<=当前字符串长度。
  2、修改。语法:Rxd,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字
符串长度。
  3、插入:语法:Ixd,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x=0,则在字
符串开头插入。限制:x不超过当前字符串长度

Output

  对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。

Sample Input

madamimadam
7
Q 1 7
Q 4 8
Q 10 11
R 3 a
Q 1 7
I 10 a
Q 2 11

Sample Output

5
1
0
2
1

HINT

  1、所有字符串自始至终都只有小写字母构成。
  2、M<=150,000
  3、字符串长度L自始至终都满足L<=100,000
  4、询问操作的个数不超过10,000个。
  对于第1,2个数据,字符串长度自始至终都不超过1,000
  对于第3,4,5个数据,没有插入操作。

Source

Solution

  相信有很多人第一眼觉得是后缀数组吧。然而后缀数组无法有效地应付修改操作

  这道题比较特殊的一点是询问个数很少,基本集中在插入和修改操作

  我们可以用$splay$维护这个字符串,插入和修改按普通$splay$做,the Longest Common Qianzhui$LCQ$需要二分答案:

  每个节点维护一个子树$hash$值,二分答案$ans$,不断检查$s[x]\sim s[x   +ans]$和$s[y]\sim s[y+ans]$的$hash$值是否一样即可

  由于有提取区间的操作,所以$treap$是无法满足的

  插入和修改的总复杂度是$O(q_1logn)$,$LCQ$的总复杂度是$O(q_2log^2n)$,因为$q_2$相对较小,所以整体可以看成$O(qlogn)$的

 #include <bits/stdc++.h>
using namespace std;
struct spaly
{
int c[], fa, val, siz, hash;
int& operator[] (int x)
{
return c[x];
}
}a[];
char s[], op[];
int pwr[]; void push_up(int k)
{
int x = a[a[k][]].siz;
a[k].siz = a[a[k][]].siz + x + ;
a[k].hash = a[a[k][]].hash * pwr[x + ] + a[k].val * pwr[x] + a[a[k][]].hash;
} void rotate(int &k, int x)
{
int y = a[x].fa, z = a[y].fa, dy = a[y][] == x;
if(k == y) k = x;
else a[z][a[z][] == y] = x;
a[y][dy] = a[x][!dy], a[a[x][!dy]].fa = y;
a[x][!dy] = y, a[y].fa = x, a[x].fa = z;
push_up(y);
} void splay(int &k, int x)
{
while(k != x)
{
int y = a[x].fa, z = a[y].fa;
if(k != y)
if(a[y][] == x ^ a[z][] == y) rotate(k, x);
else rotate(k, y);
rotate(k, x);
}
push_up(x);
} int find_kth(int k, int x)
{
if(x <= a[a[k][]].siz) return find_kth(a[k][], x);
if(x == a[a[k][]].siz + ) return k;
return find_kth(a[k][], x - a[a[k][]].siz - );
} int main()
{
int n, m, x, y, z, root, l, r, mid, ptot;
scanf("%s%d", s, &m);
n = strlen(s);
pwr[] = ;
for(int i = ; i <= ; ++i)
pwr[i] = pwr[i - ] * ;
a[].fa = , a[].siz = ;
for(int i = ; i <= n + ; ++i)
{
a[i][] = i - , a[i].fa = i + ;
a[i].val = s[i - ], push_up(i);
}
a[n + ].fa = , root = ptot = n + ;
while(m--)
{
scanf("%s", op);
if(op[] == 'R')
{
scanf("%d%s", &x, op);
splay(root, find_kth(root, x + ));
a[root].val = op[], push_up(root);
}
else if(op[] == 'I')
{
scanf("%d%s", &x, op), ++n;
splay(root, find_kth(root, x + ));
splay(a[root][], find_kth(root, x + ));
a[a[root][]][] = ++ptot;
a[ptot].val = a[ptot].hash = op[];
a[ptot].fa = a[root][], a[ptot].siz = ;
push_up(a[root][]), push_up(root);
}
else
{
scanf("%d%d", &x, &y);
if(x > y) swap(x, y);
l = , r = n - y + , z = ;
while(l < r - )
{
mid = (l + r) >> ;
splay(root, find_kth(root, x));
splay(a[root][], find_kth(root, x + mid + ));
z = a[a[a[root][]][]].hash;
splay(root, find_kth(root, y));
splay(a[root][], find_kth(root, y + mid + ));
z -= a[a[a[root][]][]].hash;
z ? r = mid : l = mid;
}
printf("%d\n", l);
}
}
return ;
}

[BZOJ1014] [JSOI2008] 火星人prefix (splay & 二分答案)的更多相关文章

  1. BZOJ 1014 [JSOI2008]火星人prefix (splay+二分答案+字符串hash)

    题目大意:维护一个字符串,支持插入字符和替换字符的操作,以及查询该字符串两个后缀的最长公共前缀长度 乍一看以为是后缀数组,然而并没有可持久化后缀数组(雾) 看题解才知道这是一道splay题,首先要对s ...

  2. BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)

    题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...

  3. BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6243  Solved: 2007[Submit] ...

  4. 【BZOJ-1014】火星人prefix Splay + 二分 + Hash

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5852  Solved: 1871[Submit] ...

  5. BZOJ 1014: [JSOI2008]火星人prefix Splay+二分

    1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...

  6. [bzoj1014](JSOI2008)火星人 prefix (Splay维护哈希)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀. 比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...

  7. bzoj1014: [JSOI2008]火星人prefix splay+hash+二分

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  8. BZOJ1014[JSOI2008]火星人prefix(splay维护hash)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  9. bzoj1014: [JSOI2008]火星人prefix splay+hash

    我写的代码好像自古以来就是bzoj不友好型的 本地跑的比std快,但是交上去巧妙被卡 答案...应该是对的,拍了好久了 #include <bits/stdc++.h> #define M ...

随机推荐

  1. PLECS_晶闸管调速系统_9w

    3. 直流电机开环调压调速系统模型搭建 (1)电路图 (2)仿真 当 α = pi / 2.7 的时候,直流电机的稳定转速大约保持很低的速度. 随着α的减少,直流电机的速度逐渐增大.当α = pi / ...

  2. IntelliJ IDEA环境配置

    [pojie](https://www.cnblogs.com/suiyueqiannian/p/6754091.html) Error running Tomcat8: Address localh ...

  3. centos出现“FirewallD is not running”怎么办

    最近在阿里云服务器centos上安装了mysql数据库,默认是不开启远端访问功能,需要设置一下防火墙,在开放默认端口号 3306时提示FirewallD is not running,经过排查发现是防 ...

  4. tomcat在centos下的操作

    一 .Tomcat启动与停止 进入Tomcat中bin所在目录 cd /usr/tomcat/bin 启动: ./startup.sh 停止: ./shutdown.sh 平常可以用这个命令来查看to ...

  5. 阿里云Aliyun_server

    一.云概念 云主机是基于云计算平台的一种虚拟的主机服务器产品 云服务器(99.999%安全性,扩展性) 特点: 1.资源分配配置灵活,安全性能强. 2.优于VPS和独立服务器产品.通俗的理解: 云主机 ...

  6. 基于agenda的Nodejs定时任务管理框架搭建

    0.背景 在大型项目中,定时任务的应用场景越来越广.一般来说,按照微服务的思想,我们会将定时任务单独部署一套服务,核心的业务接口独立到另一个服务中,从而降低相互之间的耦合程度.在需要使用定时任务时,只 ...

  7. TzObjectInspector 一例

    TzObjectInspector Github上的一个开源组件!可以做到类似Delphi IDE属性,事件面板的样式!作者持续更新中... 看起来是这个样子: 这个东西用起来并不像想象的那样可以直接 ...

  8. 有了Openvswitch和Docker,终于可以做《TCP/IP详解》的实验了!

    所有做过网络编程的程序员,想必都会看<TCP/IP详解>卷一:协议 后来出了第二版,但是由于第一版才是Rechard Stevens的原版,本人还是多次看了第一版. 对这一版印象最深的就是 ...

  9. Mysql引擎中MyISAM和InnoDB的区别有哪些?

    简单的概括一下 InnoDB:支持事务处理等不加锁读取支持外键支持行锁不支持FULLTEXT类型的索引不保存表的具体行数,扫描表来计算有多少行DELETE 表时,是一行一行的删除InnoDB 把数据和 ...

  10. 试着把.net的GC讲清楚(3)

    前两篇写的都是gc的一些概念和细节,这些东西对自己以后写代码有什么用,本篇我就准备将这些内容. root 第一篇文章中讲了GC在遍历存活对象的时候,都是从root开始的,root是一些对象的引用,例如 ...