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

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
",query(ne[x],ne[y]));
        }
    }
}
大暴力 2856 kb 1196 ms 1350 B
#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
",query(x,y));
        }
    }
}
treap 5604 kb 5512 ms 2929 B

暴力又短又快……有毒……

原文地址:https://www.cnblogs.com/Enceladus/p/5467149.html