luogu4715 「英语」Z 语言

http://www.elijahqi.win/archives/3774

题目背景
请大家注意,该题会无故 0 分。

请提交,赛后或者修好后会 Rej。

(OI 赛制(大雾

题目描述
英语是高考里最简单的一科了——至少对于小 F 来说是这样。

这一天,英语老师又在瘠义肥辞地讲着模拟题,而小 F 正玩弄着同学的电子词典。这个电子词典有一个特点,便是无法输入英文以外的字符,比如 naïve 只能为 naive,café 只能为 cafe。

小 F 非常讨厌这种设定。为了凸显这种设定的愚蠢之处,小 F 决定设计出一种字符集超大的语言——Z 语言,哪怕有时额外的字符并没有什么用。

这种语言的特点是:

字符集非常大,甚至可能有 2147483648(2 ^ {31})2147483648(231) 种字符;

每个单词由一系列两两不同的字符组成;

字符既能比较相同和不同,也能比较大小,因此之后我们用数字来表示 Z 语言中稀奇古怪的字符;

两个看起来完全不同的单词也可能是同一个单词,因为:只要两个单词中第 K 大的字符所在的位置相同,那么其实就是本质上相同的单词。例如 {1, 2, 3, 4, 5}{1,2,3,4,5} 与 {2, 3, 23, 233, 23333}{2,3,23,233,23333} 是相同的。(所以你可以用 Z 语言很方便地加密信息!)

现在,小 F 打算将 Z 语言应用到实际中。比如,他点开了一道电脑里的算法题:

给定两个字符串 A, BA,B ,求 BB 作为子串在 AA 中被匹配的次数。

小 F 当然知道这是一个可以用 KMP 解决的基础题。但是,他在用 Z 语言的匹配实现 Z-KMP 的时候遇到了问题,你能帮帮他吗?

为了验证你是不是真的明白小 F 在说什么,小 F 会修改 BB 串很多次来问你。可不准偷懒哦!

你的程序需要支持的操作详见输入输出格式。

输入输出格式
输入格式:

输入第一行两个整数 n, m, q(1 \leq n, m, q \leq 10 ^ 5)n,m,q(1≤n,m,q≤105) ,表示 A, BA,B 串的长度。

第二行 nn 个非负整数,第 ii 个表示 AA 串的第 ii 个字符 A_iAi​ (0 \leq A_i \leq 2147483647=2 ^ {31} - 1)(0≤Ai​≤2147483647=231−1) 。

第三行 mm 个非负整数,第 ii 个表示 BB 串的第 ii 个字符 B_iBi​ (0 \leq B_i \leq 2147483647=2 ^ {31} - 1)(0≤Bi​≤2147483647=231−1) 。

接下来 qq 行,每行两个正整数 x_i, c_ixi​,ci​ (1 \leq c_i \leq 2147483647=2 ^ {31} - 1)(1≤ci​≤2147483647=231−1) ,表示将 BB 串 x_ixi​ 位置上的字符由 B_{x_i}Bxi​​ 改为 c_ici​ 。

数据保证,任意时刻 AA 和 BB 均是满足前述要求的合法 Z 字符串。

输出格式:

在每次修改完成后,请输出 BB 作为子串在 AA 中被 Z-匹配 的次数。

输入输出样例
输入样例#1: 复制
5 3 2
11 7 5 3 2
3 2 1
2 5
1 6
输出样例#1: 复制
0
3
说明
样例 1 解释
在第一次修改后, {3, 5, 1}{3,5,1} 并不能被任何一个 AA 中的子串匹配上。

在第二次修改后, {6, 5, 1}{6,5,1} 能被 AA 中所有长度为 33 的串匹配上,原因是 A 是单调减的,而 B 也是单调减的,因此 AA 中所有长度为 33 的串与 BB 排名相同的处于相同位置。

子任务
子任务 1(31 \mathrm{pts}) : n, m \leq 100, q \leq 10001(31pts):n,m≤100,q≤1000 ;

子任务 2(41 \mathrm{pts}) : n, m \leq 1000, q \leq 5 \times 10 ^ 42(41pts):n,m≤1000,q≤5×104 ;

子任务 3(78 \mathrm{pts}) : n, m, q \leq 10 ^ 53(78pts):n,m,q≤105 。

在splay上维护每个位置的hash值 hash值的定义为 第几大的值出现在哪里

然后先把a序列所有长度为m的hash值都存在hash表里

然后每次修改b序列的时候 获得一个hash值 然后直接去hash表里询问一下出现次数即可

#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int N=1e5+10;
const int g=11117;
const int mod=100003;
struct node{
    ll s;int next,v;
}data[N];
ll p[N],hs[N],w[N],S;int size[N],fa[N],c[N][2],h[N],num,b[N],n,m,q,rt,v[N];
inline void update(int x){
    int l=c[x][0],r=c[x][1];
    size[x]=size[l]+size[r]+1;
    hs[x]=hs[l]+p[size[l]]*w[x]+p[size[l]+1]*hs[r];
}
inline void rotate(int x,int &tar){
    int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
    if (y==tar) tar=x;else c[z][c[z][1]==y]=x;
    fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
    c[y][l]=c[x][r];c[x][r]=y;update(y);update(x);
}
inline void splay(int x,int &tar){
   while(x!=tar){
        int y=fa[x],z=fa[y];
        if (y!=tar){
            if (c[y][0]==x^c[z][0]==y) rotate(x,tar);else rotate(y,tar);
        }rotate(x,tar);
    }
}
inline void insert1(int &x,int id,int f){
    if (!x) {x=id;fa[x]=f;update(x);splay(x,rt);return;}
    if (v[id]<v[x]) insert1(c[x][0],id,x);
    else insert1(c[x][1],id,x);
}
//unordered_map<ll,int> mm;
inline void ins(ll s){
    //++mm[s];return;
    int x=s%mod;
    for (int i=h[x];i;i=data[i].next){
        if (s==data[i].s) {++data[i].v;return;}
    }
    data[++num].s=s;data[num].v=1;data[num].next=h[x];h[x]=num;
}
inline int query(ll s){
    //return mm[s];
    int x=s%mod;
    for (int i=h[x];i;i=data[i].next){
        if (s==data[i].s) return data[i].v;
    }return 0;
}
inline void del(int x){
    splay(x,rt);
    if(!(c[x][0]*c[x][1])){rt=c[x][0]+c[x][1];fa[rt]=0;c[x][0]=c[x][1]=0;return;}
    int succ=c[x][1],pre=c[x][0];
    while(c[pre][1]) pre=c[pre][1];
    while(c[succ][0]) succ=c[succ][0];
    splay(pre,rt);splay(succ,c[rt][1]);c[succ][0]=0;fa[x]=0;update(succ);update(rt);

}
int main(){
    freopen("4715.in","r",stdin);
    n=read();m=read();q=read();p[0]=1;
    for (int i=1;i<=n;++i) v[i]=read();
    for (int i=1;i<=n;++i) w[i]=i,p[i]=p[i-1]*g;
    for (int i=1;i<=m;++i) insert1(rt,i,0),S+=p[i-1],b[i]=read();
    for (int i=m;i<=n;++i){
        ins(hs[rt]-S*(i-m));if (i==n) break;
        del(i-m+1);insert1(rt,i+1,0);
    }rt=0;memset(c,0,sizeof(c));memset(fa,0,sizeof(fa));
    for (int i=1;i<=m;++i) v[i]=b[i],insert1(rt,i,0);
    while(q--){
        int x=read(),cc=read();del(x);c[x][0]=c[x][1]=0;
        v[x]=cc;insert1(rt,x,0);
        printf("%d\n",query(hs[rt]));
    }
    return 0;
}
阅读更多
版权声明:辣鸡蒟蒻的blog https://blog.csdn.net/elijahqi/article/details/80733262
个人分类: splay hash
上一篇codeforces 992 C Nastya and a Wardrobe
下一篇bzoj 4712 洪水
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭