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
7
Q 1 7
Q 4 8
Q 10 11
R 3 a
Q 1 7
I 10 a
Q 2 11
Sample Output
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个数据,没有插入操作。
用splay维护hash值
当前点update的时候就用俩儿子的hash值计算一下字符串(左儿子+x+右儿子)新的hash值
hash一开始被卡了素质三连(模数1e4+7不被卡就有鬼了……)
中途有个变量打错了还过了样例emmm……
喜闻乐见样例是有多弱
?1 #include<iostream> ?2 #include<cstring> ?3 #include<cstdio> ?4 #define N (200000+100) ?5 #define MOD (19260817) ?6 using namespace std; ?7 int Val[N],Size[N],Son[N][2],Father[N],Sum[N],hash[N]; ?8 int Root,n,m,x,y,p,sz; ?9 char opt[15],ch[15],a[N]; 10 ?11 int Get(int x) {return Son[Father[x]][1]==x;} 12 void Clear(int x) {Sum[x]=Father[x]=Son[x][0]=Son[x][1]=Size[x]=Val[x]=0;} 13 ?14 void Update(int x) 15 { 16 ????int l=Son[x][0],r=Son[x][1]; 17 ????Size[x]=Size[l]+Size[r]+1; 18 ????Sum[x]=((long long)Sum[l]*hash[Size[r]+2]%MOD + (long long)Val[x]*hash[Size[r]+1] + Sum[Son[x][1]])%MOD; 19 } 20 ?21 void Rotate(int x) 22 { 23 ????int wh=Get(x); 24 ????int fa=Father[x],fafa=Father[fa]; 25 ????Father[fa]=x; 26 ????Son[fa][wh]=Son[x][wh^1]; 27 ????if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 28 ????Father[x]=fafa; 29 ????Son[x][wh^1]=fa; 30 ????if (fafa) Son[fafa][Son[fafa][1]==fa]=x; 31 ????Update(fa); 32 ????Update(x); 33 } 34 ?35 void Splay(int x,int tar) 36 { 37 ????for (int fa; (fa=Father[x])!=tar; Rotate(x)) 38 ????????if (Father[fa]!=tar) 39 ????????????Rotate(Get(fa)==Get(x)?fa:x); 40 ????if (!tar) Root=x; 41 } 42 ?43 int Findx(int x) 44 { 45 ????int now=Root; 46 ????while (1) 47 ????????if (Size[Son[now][0]]>=x) 48 ????????????now=Son[now][0]; 49 ????????else 50 ????????{ 51 ????????????x-=Size[Son[now][0]]; 52 ????????????if (x==1) 53 ????????????{ 54 ????????????????Splay(now,0); 55 ????????????????return now; 56 ????????????} 57 ????????????x--; 58 ????????????now=Son[now][1]; 59 ????????} 60 } 61 ?62 void Build(int l,int r,int fa) 63 { 64 ????if (l>r) return; 65 ????int mid=(l+r)>>1; 66 ????Build(l,mid-1,mid); 67 ????Build(mid+1,r,mid); 68 ????Father[mid]=fa; 69 ????Son[fa][mid>fa]=mid; 70 ????Val[mid]=a[mid]-‘a‘+1; 71 ????Update(mid); 72 } 73 ?74 int Split(int x,int y) 75 { 76 ????int xx=Findx(x),yy=Findx(y); 77 ????Splay(xx,0); 78 ????Splay(yy,xx); 79 ????return Son[yy][0]; 80 } 81 ?82 bool check(int len) 83 { 84 ????int xx=Split(x,x+len+1); 85 ????int ans1=Sum[xx]; 86 ????int yy=Split(y,y+len+1); 87 ????int ans2=Sum[yy]; 88 ????return ans1==ans2; 89 } 90 ?91 int main() 92 { 93 ????hash[1]=1; 94 ????for (int i=2; i<=200000; ++i) 95 ????????hash[i]=hash[i-1]*27%MOD; 96 ?97 ????scanf("%s%d",a+2,&m); 98 ????n=strlen(a+2); 99 ????Build(1,n+2,0);100 ????Root=(n+3)>>1;101 ????sz=n+2;102 103 104 ????for (int i=1; i<=m; ++i)105 ????{106 ????????scanf("%s",opt);107 ????????if (opt[0]==‘Q‘)108 ????????{109 ????????????scanf("%d%d",&x,&y);110 ????????????int l=1,r=Size[Root]-max(x,y)-1,ans=0;111 ????????????while (l<=r)112 ????????????????if (check((l+r)>>1))113 ????????????????{114 ????????????????????l=((l+r)>>1)+1;115 ????????????????????ans=l-1;116 ????????????????}117 ????????????????else118 ????????????????????r=((l+r)>>1)-1;119 ????????????printf("%d\n",ans);120 ????????}121 ????????if (opt[0]==‘R‘)122 ????????{123 ????????????scanf("%d%s",&p,ch);124 ????????????Findx(p+1);125 ????????????Val[Root]=ch[0]-‘a‘+1;126 ????????????Update(Root);127 ????????}128 ????????if (opt[0]==‘I‘)129 ????????{130 ????????????scanf("%d%s",&p,ch);131 ????????????Split(p+1,p+2);132 ????????????int x=Son[Root][1];133 ????????????Val[++sz]=ch[0]-‘a‘+1;134 ????????????Size[sz]=1;135 ????????????Father[sz]=x;136 ????????????Son[x][0]=sz;137 ????????????Splay(sz,0);138 ????????}139 ????}140 }
1014. [JSOI2008]火星人【平衡树-splay+hash】
原文地址:https://www.cnblogs.com/refun/p/8685559.html