题意:
给定一个字符串,要求维护两种操作:
I:在字符串中插入一个字符;
Q:询问某两个位置开始的LCP;
插入操作<=200,字符串长度<=5w,查询操作<=2w;
题解:
第一道RKhash题,插入太少让这题变成了傻题;
注意题中描述的各种恶心的下标讨论;
插入下标是当前下标,而查询是原下标;
查询就是二分答案,利用RKhash快速合并的性质搞搞;
复杂度O(mlogn+100n);
单组数据,略微卡常;
代码:
#include<stdio.h> #include<string.h> #include<algorithm> #define N 51000 #define mod 1000000009ll using namespace std; typedef unsigned long long ull; int p[N],len; char str[N],op[10]; ull hash[N],pow[N]; void Build(int x) { for(int i=x;i<=len;i++) hash[i]=(hash[i-1]*131+str[i])%mod; } int query(int x,int y) { int l=0,r=len-max(x,y)+1; while(l<=r) { int mid=l+r>>1; if((hash[x+mid-1]-hash[x-1]*pow[mid]%mod+mod)%mod== (hash[y+mid-1]-hash[y-1]*pow[mid]%mod+mod)%mod) l=mid+1; else r=mid-1; } return r; } int main() { int n,m,i,j,k,x,y; pow[0]=1; for(i=1;i<N;i++) pow[i]=pow[i-1]*131%mod; scanf("%s",str+1); n=len=strlen(str+1); scanf("%d",&m); Build(1); for(i=1;i<=n;i++) p[i]=i; for(i=1;i<=m;i++) { scanf("%s",op); if(op[0]=='I') { scanf("%s%d",op,&x); if(x>len) x=len+1; memcpy(str+x+1,str+x,sizeof(char)*(len-x+1)); str[x]=op[0]; for(j=n;j>=1;j--) { if(p[j]>=x) p[j]++; else break; } len++; Build(x); } else { scanf("%d%d",&x,&y); printf("%d\n",query(p[x],p[y])); } } return 0; }
原文地址:http://blog.csdn.net/ww140142/article/details/47045873