Hash_1014: [JSOI2008]火星人prefix

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef unsigned int ll;
 8 #define maxn 150005
 9 #define p 53
10 int n,m,root,tot,fa[maxn],son[maxn][2],size[maxn];
11 ll val[maxn],sum[maxn],bin[maxn];
12 char st[maxn],op[5];
13 void read(int &x){
14     x=0; int f=1; char ch;
15     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) f=-1;
16     for (;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; x*=f;
17 }
18 struct SPLAY{
19     int which(int x){
20         return son[fa[x]][1]==x;
21     }
22     void updata(int x){
23         int ls=son[x][0],rs=son[x][1];
24         size[x]=size[ls]+size[rs]+1;
25         sum[x]=sum[rs]+val[x]*bin[size[rs]]+sum[ls]*bin[1+size[rs]];
26     }
27     int build(int l,int r){
28         int x; if (l>r) return 0; int mid=(l+r)>>1;
29         if (mid==0) x=n+1,val[x]=0;
30         else if (mid==n+1) x=n+2,val[x]=0;
31         else x=mid,val[x]=st[x]-‘a‘; size[x]=1;
32         son[x][0]=build(l,mid-1),son[x][1]=build(mid+1,r),updata(x);
33         if (son[x][0]) fa[son[x][0]]=x;
34         if (son[x][1]) fa[son[x][1]]=x;
35         return x;
36     }
37     void rotata(int x){
38         int y=fa[x],d=which(x),dd=which(y);
39         if (fa[y]) son[fa[y]][dd]=x; fa[x]=fa[y];
40         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1];
41         fa[y]=x,son[x][d^1]=y,updata(y);
42     }
43     void splay(int x,int goal){
44         while (fa[x]!=goal){
45             if (fa[fa[x]]==goal) rotata(x);
46             else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
47             else rotata(x),rotata(x);
48         }
49         if (goal==0) root=x; updata(x);
50     }
51     int kth(int x){
52         int y=root,ls,rs; if (!root) return 0;
53         for (;;){
54             ls=son[y][0],rs=son[y][1];
55             if (size[ls]+1==x) return y;
56             else if (size[ls]>=x) y=ls;
57             else x-=size[ls]+1,y=rs;
58         }
59     }
60     bool check(int x,int y,int len){
61         int t1,t2; t1=kth(x),t2=kth(x+len+1);
62         ll z;splay(t1,0),splay(t2,t1),z=sum[son[t2][0]];
63         t1=kth(y),t2=kth(y+len+1); splay(t1,0),splay(t2,t1);
64         return z==sum[son[t2][0]];
65     }
66 }Splay;
67 void query(int x,int y){
68     int l=1,r,mid,ans=0; r=min(tot-2-x+1,tot-2-y+1);
69     while (l<=r){
70         mid=(l+r)>>1;
71         if (Splay.check(x,y,mid)==1) ans=mid,l=mid+1;
72         else r=mid-1;
73     }printf("%d\n",ans);
74 }
75 int main(){
76     bin[0]=1; for (int i=1;i<=150000;i++) bin[i]=bin[i-1]*p;
77     scanf("%s",st+1),n=strlen(st+1);
78     root=Splay.build(0,n+1); tot=n+2;
79     read(m);
80     for (int x,y;m;m--){
81         scanf("%s",op+1);
82         if (op[1]==‘Q‘) read(x),read(y),query(x,y);
83         else if (op[1]==‘R‘) read(x),scanf("%s",op+1),x=Splay.kth(x+1),Splay.splay(x,0),val[x]=op[1]-‘a‘,Splay.updata(x);
84         else{
85             read(x),scanf("%s",op+1),++tot,val[tot]=op[1]-‘a‘,size[tot]=1;
86             int t1=Splay.kth(x+1),t2=Splay.kth(x+2); Splay.splay(t1,0),Splay.splay(t2,t1);
87             fa[tot]=t2,son[t2][0]=tot,Splay.updata(t2),Splay.splay(tot,0);
88         }
89     }
90     return 0;
91 }

Splay维护,询问时二分答案,Hash判定,我用的是53进制。

splay,二分,Hash。

时间: 2024-11-09 19:13:06

Hash_1014: [JSOI2008]火星人prefix的相关文章

JSOI2008 火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2918  Solved: 866[Submit][Status] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人

1014: [JSOI2008]火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7820  Solved: 2487 [Submit][Status][Discuss] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam, 我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a

【bzoj1014】[JSOI2008]火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6031  Solved: 1917[Submit][Status][Discuss] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d

bzoj 1014: [JSOI2008]火星人prefix hash &amp;&amp; splay

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3154  Solved: 948[Submit][Status] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人

BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int maxn = 100009; const int P = 1000173169; ull K[maxn]; int N; char S[maxn]; struct Node { Node *ch[2], *p; int s, v; ull h; inline void

求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4164  Solved: 1277[Submit][Status][Discuss] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d

【BZOJ 1014】 [JSOI2008]火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3471  Solved: 1065 [Submit][Status] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,

bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix

http://www.lydsy.com/JudgeOnline/problem.php?id=1014 两个后缀的最长公共前缀:二分+hash 带修改带插入:splay维护 #include<cstdio> #include<cstring> #include<iostream> #define L 100001 typedef unsigned long long ULL; using namespace std; char s[L+4]; int tot,root

【bzoj1014】: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分

[bzoj1014]: [JSOI2008]火星人 用平衡树维护字符串的hash 然后询问的时候二分一下就好了 1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 #