poj 2758 && BZOJ 2258 Checking the Text 文本校对
Description
为了给Wind买生日礼物,Jiajia不得不找了一份检查文本的工作。这份工作很无聊:给你一段文本
要求比对从文本中某两个位置开始能匹配的最大长度是多少。但比无聊更糟糕的是,Jiajia的经理
还可能往文本里面插入一些字符。
Jiajia想用一个程序来解决这些繁琐的工作。这个程序的速度要足够快,因为Wind的生日就快要到了
Jiajia必须赚到足够多的钱,也就是处理足够多的文本。
Input
输入文件第一行是原始文本。
输入文件第二行是操作数n。此后n行,每行描述一条命令,命令有两种形式:
I ch p:表示将一个字符ch插入到当前文本的第p个字符之前,如果p大于当前文本长度则表示插入到当前文本末尾;
Q i j:表示询问当前文本从原始文本的第i个和第j个字符现在所在的位置开始能匹配的字符是多少。
你可以认为文本初始长度不超过50000,I命令最多200条,Q命令最多20000条。
Output
对于每条Q命令输出一行,为最长匹配长度。
Sample Input
abaab
5
Q 1 2
Q 1 3
I a 2
Q 1 2
Q 1 3
5
Q 1 2
Q 1 3
I a 2
Q 1 2
Q 1 3
Sample Output
0
1
0
3
直接hash暴力重构==1196 ms(bzoj)
treap维护hash==5512 ms(bzoj)
spaly维护hash==TLE
gg……
感谢居神贡献权限号
#include<cstdio> #include<algorithm> #include<cstring> #define MN 100001 using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } unsigned long long hash[MN],mi[MN]; char c[MN],p[2]; int n,m,ne[MN],pos,len,x,y; inline void build(int x){ for (int i=x;i<=len;i++) hash[i]=hash[i-1]*131+c[i]; } inline int query(int x,int y){ if (x>y) swap(x,y); int l=0,r=len-y+1,mid; while (l<r){mid=(l+r+1)>>1;if (hash[x+mid-1]-hash[x-1]*mi[mid]==hash[y+mid-1]-hash[y-1]*mi[mid]) l=mid;else r=mid-1;} return l; } int main(){ scanf("%s",c+1); n=read(); m=len=strlen(c+1); mi[0]=1; for (int i=1;i<=m+200;i++) mi[i]=mi[i-1]*131; for (int i=1;i<=len;i++) ne[i]=i; build(1); for (int i=1;i<=n;i++){ scanf("%s",p); if (p[0]=='I'){ scanf("%s",p);pos=read(); if (pos>len) pos=len+1; for (int i=len;i>=pos;i--) c[i+1]=c[i]; c[pos]=p[0];len++; build(pos); for (int i=m;i;i--) if (ne[i]>=pos) ne[i]++;else break; }else{ x=read();y=read(); printf("%d\n",query(ne[x],ne[y])); } } }
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define MN 100001 using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } unsigned long long mi[MN]; char c[MN],p[2]; int n,m,ne[MN],pos,len,x,y; struct tree{ int l,r,s,f,fa; unsigned long long h,c; tree(){ l=r=s=h=c=0; } }; struct s_tree{ int root,size; tree t[100001]; s_tree(){ root=size=0; } inline void up(int x){ t[x].h=(t[t[x].l].h*131+t[x].c)*mi[t[t[x].r].s]+t[t[x].r].h; } inline void rir(int &x){ int k=t[x].r; t[x].r=t[k].l; t[k].l=x; t[t[x].r].fa=x; t[k].fa=t[x].fa; t[x].fa=k; t[k].s=t[x].s; t[x].s=1+t[t[x].l].s+t[t[x].r].s; t[k].h=t[x].h;up(x); x=k; } inline void lir(int &x){ int k=t[x].l; t[x].l=t[k].r; t[k].r=x; t[t[x].l].fa=x; t[k].fa=t[x].fa; t[x].fa=k; t[k].s=t[x].s; t[x].s=1+t[t[x].l].s+t[t[x].r].s; t[k].h=t[x].h;up(x); x=k; } inline void insert(int &p,int x,int c,int f){ if (!p){ p=++size; t[p].c=c; t[p].h=c; t[p].s=1; t[p].f=rand(); t[p].fa=f; }else{ t[p].s++; if (t[t[p].l].s+1>=x){ insert(t[p].l,x,c,p); if (t[t[p].l].f<t[p].f) lir(p); }else{ insert(t[p].r,x-1-t[t[p].l].s,c,p); if (t[t[p].r].f<t[p].f) rir(p); } } up(p); } inline int ne(int x){ int mmh=0; while (x){ mmh+=t[t[x].l].s+1; while (t[x].fa&&t[t[x].fa].l==x) x=t[x].fa; x=t[x].fa; } return mmh; } inline unsigned long long hash(int p,int x){ if ((!x)||(!p)) return 0; if (t[t[p].l].s==x-1) return t[t[p].l].h*131+t[p].c;else if (t[t[p].l].s>=x) return hash(t[p].l,x);else return (t[t[p].l].h*131+t[p].c)*mi[x-t[t[p].l].s-1]+hash(t[p].r,x-1-t[t[p].l].s); } }t; inline int query(int x,int y){ x=t.ne(x);y=t.ne(y); if (x>y) swap(x,y); int l=0,r=len-y+1,mid; while (l<r){mid=(l+r+1)>>1;if (t.hash(t.root,x+mid-1)-t.hash(t.root,x-1)*mi[mid]==t.hash(t.root,y+mid-1)-t.hash(t.root,y-1)*mi[mid]) l=mid;else r=mid-1;} return l; } int main(){ scanf("%s",c+1); n=read(); m=len=strlen(c+1); mi[0]=1; for (int i=1;i<=1e5;i++) mi[i]=mi[i-1]*131; for (int i=1;i<=len;i++) ne[i]=i; for (int i=1;i<=len;i++) t.insert(t.root,i,c[i],0); for (int i=1;i<=n;i++){ scanf("%s",p); if (p[0]=='I'){ scanf("%s",p);pos=read(); if (pos>len) pos=len+1;t.insert(t.root,pos,p[0],0); len++; }else{ x=read();y=read(); printf("%d\n",query(x,y)); } } }
暴力又短又快……有毒……