BZOJ2105: 增强型LCP

2105: 增强型LCP

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 366  Solved: 86
[Submit][Status]

Description

Input

Output

对于每个Lcp(a,b)操作输出最长公共前缀

Sample Input

47
abab
L 13
A 1 ab
L 1 3
C 56 cb
L 1 3
D 1 2
L 1 3

Sample Output

2
4
2
0

HINT

Source

题解:
这题。。。
原来一直以为是个splay练手题,于是昨天来写。。。
2h没调出来,今天来了发现pushup写错了。。。T_T
然后就是狂T了。。。
看题解发现我们暴力重构写hash就行了,因为修改少,我也是醉了。。。
然后终于会了字符串的hash算法
我们另b[i]=si-sn的hash值,递推式b[i]=b[i+1]*base+s[i]
然后我们要得到从i开始的len长度的hash就是 b[i]-b[i+len]*a[len]  a[len]表示base^len
还有c++的字符串问题
s,insert(pos,st) 表示在pos前插入st
s.erase(pos,len)表示从pos开始删除len的字符,包括pos
代码:

  1 #include<cstdio>
  2
  3 #include<cstdlib>
  4
  5 #include<cmath>
  6
  7 #include<cstring>
  8
  9 #include<algorithm>
 10
 11 #include<iostream>
 12
 13 #include<vector>
 14
 15 #include<map>
 16
 17 #include<set>
 18
 19 #include<queue>
 20
 21 #include<string>
 22
 23 #define inf 1000000000
 24
 25 #define maxn 1000000+5
 26
 27 #define maxm 500+100
 28
 29 #define eps 1e-10
 30
 31 #define ull unsigned long long
 32
 33 #define pa pair<int,int>
 34
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42
 43 #define mod 1000000007
 44 #define base 13131
 45
 46 using namespace std;
 47
 48 inline int read()
 49
 50 {
 51
 52     int x=0,f=1;char ch=getchar();
 53
 54     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 55
 56     while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();}
 57
 58     return x*f;
 59
 60 }
 61 int n,m,q;
 62 ull a[maxn],b[maxn];
 63 char ch[maxn];
 64 string s;
 65 inline void rebuild()
 66 {
 67     n=s.length();
 68     b[n-1]=s[n-1];
 69     for3(i,n-2,0)b[i]=b[i+1]*base+(ull)s[i];
 70 }
 71 inline ull get(int x,int l){return b[x]-b[x+l]*a[l];}
 72
 73 int main()
 74
 75 {
 76
 77     freopen("input.txt","r",stdin);
 78
 79     freopen("output.txt","w",stdout);
 80
 81     n=read();q=read();
 82     scanf("%s",ch);s=ch;
 83     a[0]=1;
 84     for1(i,maxn-1)a[i]=a[i-1]*(ull)base;
 85     rebuild();
 86     while(q--)
 87     {
 88         scanf("%s",ch);
 89         if(ch[0]==‘L‘)
 90         {
 91             int x=read()-1,y=read()-1,l=0,r=n-y;
 92             while(l<=r)
 93             {
 94                 int mid=(l+r)>>1;
 95                 if(get(x,mid)==get(y,mid))l=mid+1;else r=mid-1;
 96             }
 97             printf("%d\n",r);
 98         }
 99         else if(ch[0]==‘A‘)
100         {
101             int x=read()-1;
102             scanf("%s",ch);
103             s.insert(x,ch);
104             rebuild();
105         }
106         else if(ch[0]==‘C‘)
107         {
108             int x=read()-1,y=read()-1;
109             scanf("%s",ch);
110             for2(i,x,y)s[i]=ch[i-x];
111             rebuild();
112         }
113         else
114         {
115             int x=read()-1,y=read()-1;
116             s.erase(x,y-x+1);
117             rebuild();
118         }
119     }
120
121     return 0;
122
123 } 

再贴一下splay的代码,sad story。。。

代码:

  1 #include<cstdio>
  2
  3 #include<cstdlib>
  4
  5 #include<cmath>
  6
  7 #include<cstring>
  8
  9 #include<algorithm>
 10
 11 #include<iostream>
 12
 13 #include<vector>
 14
 15 #include<map>
 16
 17 #include<set>
 18
 19 #include<queue>
 20
 21 #include<string>
 22
 23 #define inf 1000000000
 24
 25 #define maxn 1000000+5
 26
 27 #define maxm 500+100
 28
 29 #define eps 1e-10
 30
 31 #define ull unsigned long long
 32
 33 #define pa pair<int,int>
 34
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42
 43 #define mod 1000000007
 44
 45 using namespace std;
 46
 47 inline int read()
 48
 49 {
 50
 51     int x=0,f=1;char ch=getchar();
 52
 53     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 54
 55     while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();}
 56
 57     return x*f;
 58
 59 }
 60 int n,m,q,xx,yy,rt,tot,id[maxn],s[maxn],c[maxn][2],fa[maxn];
 61 ull v[maxn],sum[maxn],hash[maxn];
 62 char st[maxn];
 63 inline void pushup(int x)
 64 {
 65     if(!x)return;
 66     int l=c[x][0],r=c[x][1];
 67     s[x]=s[l]+s[r]+1;
 68     sum[x]=sum[r]+v[x]*hash[s[r]]+sum[l]*hash[s[r]+1];
 69     //if(x==7)cout<<x<<‘ ‘<<l<<‘ ‘<<r<<‘ ‘<<sum[x]<<‘ ‘<<sum[r]<<‘ ‘<<s[r]<<‘ ‘<<v[x]<<endl;
 70 }
 71 inline void rotate(int x,int &k)
 72 {
 73     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
 74     if(y!=k)c[z][c[z][1]==y]=x;else k=x;
 75     //cout<<x<<‘ ‘<<y<<‘ ‘<<z<<endl;
 76     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
 77     c[y][l]=c[x][r];c[x][r]=y;
 78     pushup(y);pushup(x);
 79 }
 80 inline void splay(int x,int &k)
 81 {
 82     while(x!=k)
 83     {
 84         int y=fa[x],z=fa[y];
 85         if(y!=k)
 86         {
 87             if((c[z][0]==y)^(c[y][0]==x))rotate(x,k);else rotate(y,k);
 88         }
 89         rotate(x,k);
 90     }
 91 }
 92 void build(int l,int r,int f)
 93 {
 94     if(l>r)return;
 95     int mid=(l+r)>>1,x=id[mid]=++tot,y=fa[x]=id[f];
 96     v[x]=st[mid];c[y][mid>f]=x;
 97     if(l==r)
 98     {
 99        sum[x]=v[x];s[x]=1;
100        return;
101     }
102     build(l,mid-1,mid);build(mid+1,r,mid);
103     pushup(x);
104     //cout<<x<<‘ ‘<<c[x][0]<<‘ ‘<<c[x][1]<<‘ ‘<<sum[x]<<endl;
105 }
106 inline int find(int x,int k)
107 {
108     int l=c[x][0],r=c[x][1];
109     if(s[l]+1==k)return x;
110     else if(s[l]>=k)return find(l,k);
111     else return find(r,k-s[l]-1);
112 }
113 inline void split(int l,int r)
114 {
115     xx=find(rt,l);yy=find(rt,r);
116     splay(xx,rt);splay(yy,c[xx][1]);
117 }
118 inline void print(int x)
119 {
120     if(!x)return;
121     //cout<<x<<‘ ‘<<c[x][0]<<‘ ‘<<c[x][1]<<"AAAAAAAAAAA"<<endl;
122     print(c[x][0]);
123     cout<<(char)v[x];
124     print(c[x][1]);
125 }
126 inline ull query(int l,int r)
127 {
128     split(l,r+2);
129     //cout<<l<<‘ ‘<<r<<endl;
130     //cout<<l<<‘ ‘<<r<<‘ ‘<<c[y][0]<<‘ ‘<<sum[c[y][0]]<<‘ ‘<<v[c[y][0]]<<endl;
131     //print(c[yy][0]);cout<<endl;
132     //cout<<sum[c[yy][0]]<<endl;
133     return sum[c[yy][0]];
134 }
135
136 int main()
137
138 {
139
140     n=read();q=read();
141     hash[0]=1;
142     for1(i,maxn-1)hash[i]=hash[i-1]*(ull)150;
143     scanf("%s",st+2);m=strlen(st+2);
144     st[1]=st[m+1+1]=‘a‘;
145     build(1,m+2,0);rt=id[(1+m+2)>>1];
146     //cout<<id[2]<<‘ ‘<<id[3]<<endl;
147     while(q--)
148     {
149         char ch[10];scanf("%s",ch);
150         //cout<<"AAAAAAAAAA"<<endl;
151         if(ch[0]==‘L‘)
152         {
153             int a=read(),b=read(),l=0,r=s[rt]-2-b+1;
154             while(l<=r)
155             {
156                 int mid=(l+r)>>1;
157                 //cout<<l<<‘ ‘<<mid<<‘ ‘<<r<<endl;
158                 if(query(a,a+mid-1)==query(b,b+mid-1))l=mid+1;else r=mid-1;
159             }
160             printf("%d\n",r);
161         }
162         else if(ch[0]==‘A‘)
163         {
164             int a=read();//cout<<a<<endl;
165             scanf("%s",st+1);m=strlen(st+1);
166             build(1,m,0);
167             split(a,a+1);
168             fa[c[yy][0]=id[(1+m)>>1]]=yy;
169             pushup(yy);pushup(xx);
170         }
171         else if(ch[0]==‘C‘)
172         {
173             int a=read(),b=read();
174             scanf("%s",st+1);m=strlen(st+1);
175             build(1,m,0);
176             split(a,b+2);
177             fa[c[yy][0]=id[(1+m)>>1]]=yy;
178             pushup(yy);pushup(xx);
179         }
180         else
181         {
182             int a=read(),b=read();
183             split(a,b+2);
184             c[yy][0]=0;
185             pushup(yy);pushup(xx);
186         }
187     }
188
189     return 0;
190
191 } 

时间: 2024-11-09 02:04:54

BZOJ2105: 增强型LCP的相关文章

hdu 3518 Boring counting 后缀数组LCP

题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output 2 3 3 思路:套用后缀数组求解出sa数组和height数组,之后枚举后缀的公共前缀长度i,由于不能重叠,所以计数的是相邻height不满足LCP >= i的. 写写对后缀数组倍增算法的理解: 1.如果要sa数组对应的值也是1~n就需要在最后加上一个最小的且不出现的字符'#',里面y[]是利用sa数

后缀数组 hash求LCP BZOJ 4310: 跳蚤

后缀数组的题博客里没放进去过..所以挖了一题写写 充实下博客 顺便留作板子.. 一个字符串S中 内容不同的子串 有 sigma{n-sa[i]+1-h[i]}   (噢 这里的h[]就是大家熟知的height[]) 所以l=1,r=上述sigma 二分 答案是字典序第几大的子串. 然后 求S中第k大的子串W : 因为h[i]是与i-1有关的 所以要从n downto 1,k-=n-sa[i]+1-h[i] 至 k再减就非正了 显然这样扫过来 子串字典序是递减的  因此可以得到第k大子串W 然后再

Java 增强型的for循环 for each

For-Each循环也叫增强型的for循环,或者叫foreach循环. For-Each循环是JDK5.0的新特性(其他新特性比如泛型.自动装箱等). For-Each循环的加入简化了集合的遍历. 其语法如下: for(type element: array) {       System.out.println(element); } For-Each循环的缺点:丢掉了索引信息. 当遍历集合或数组时,如果需要访问集合或数组的下标,那么最好使用旧式的方式来实现循环或遍历,而不要使用增强的for循

25.使用Iterator和增强型for循环遍历Map集合

/** * 宠物类,狗狗和企鹅的父类. */ public abstract class Pet { protected String name = "无名氏";// 昵称 protected int health = 100;// 健康值 protected int love = 0;// 亲密度 public abstract void eat(); //抽象方法eat(),负责宠物吃饭功能. /** * 无参构造方法. */ public Pet() { } /** * 有参构造

增强型for循环,用于遍历数组元素

/** * */ package com.cn.u4; /** * @author Administrator *增强型for */ public class ZhengQiangFor { public static void main(String[] args) { int[] nums={10,2,4,8,5}; for(int i:nums){//增强型for是把nums中的元素依次赋给i System.out.println(i); } } }

hdu-5635 LCP Array

LCP Array Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 358    Accepted Submission(s): 102 Problem Description Peter has a string s=s1s2...sn, let suffi=sisi+1...sn be the suffix start with 

结对项目-增强型科学计算器

题目:增强型计算器   1. 题目简介:       项目采用结对编程方式编写,完成一个图形界面的计算器,可以在标准计算器和科学计算器之间切换,标准计算器的基本功能有:加.减.乘.除基本算术运算:科学计算器的基本功能有:三角函数.进制转换.对数.阶乘:在普通科学计算器基础上新增加:求解一元二次方程,求解勾股定理. 2.基本功能与要求: 1).标准计算器:加.减.乘.除.求平方根: 2).科学计算器:进制转换.求解三角函数.对数运算.阶乘: 3).一元二次方程:求一元二次方程的解: 4).勾股定理

增强型for循环

增强型for循环. 上网查了下,增强型for循环是Java1.5的新特性.所谓“增强型的for 循环”,主要也是针对容器的.使用该项特性时,开发者可以将“利用iterator 遍历容器”的逻辑交给编译器来处理. 例如一个旧的例子: String name[]={"张三","李四","王五"}; for(int i=0;i<name.length;i++){ System.out.println(name[i]); } 使用增强型的for循环

poj 1743 最长不重叠重复子串 后缀数组+lcp+二分

题比较容易读懂,但是建模需动点脑子: 一个子串加常数形成的子串认为跟子串相同,求最长不重叠重复子串 题目中说 is disjoint from (i.e., non-overlapping with) at least one of its other appearance(s) 意味着不能重叠,举个例子 1, 2,3,  52, 53,54 1,2, 3和 52, 53,54满足题意,差值为51 枚举差值肯定不行------看了题解明白的:: 后项减去前一项得到: 1,1,1,49,1,1