ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P5212 SubString

2022-04-23 09:32:45  阅读:199  来源: 互联网

标签:ch P5212 int tr SubString fa np define


大意

给你一个初始字符串。现在需要你实现两种操作,第一种是在字符串最后插入字符,第二种是给出一个字符串,求这个字符串在整个字符串中出现的次数。强制在线。

Sol

牛逼题啊。首先对于动态插入字符的问题,别的算法肯定是行不通的(可能哈希可以搏一搏),所以我们考虑十分贴合这题的 SAM。SAM 本身就是采用增量法每次 \(O(1)\) 构造的。这样就轻松解决了插入字符的问题。

好接下来考虑这个查询。我们发现,对于求子串出现次数的做法,似乎只能是在 SAM 构造的 Parent Tree 上对每个节点子树求和,这个做法非常显然,因为子串出现次数实际上就是 endpos 集合的大小,具体可以见我的博客

但是不难发现,这样的方法在强制在线的情况下会寄掉,因为我们需要在建好 SAM 之后跑一次大法师。所以,我们需要考虑一个更加高妙的想法。

思考我们在构造 Parent Tree 的时候,会进行什么操作?断一条边,连一条边,然后询问子树中权值和(因为在 SAM 中复制的节点不对父亲的 endpos 大小产生影响)。断边连边的操作容易使我们想到直接无脑用维护子树的 LCT 来做。这样 SAM 插入一次就是 \(O(\log n)\) 的了。然后最终复杂度是 \(O(n\log n)\),卡卡就过了?

对于具体实现,我们考虑 Parent Tree 是有一个固定的点的,所以完全不需要 makeroot 操作(而且也不能,因为这样一来就影响了子树的问题)。而且,我们在实现 LCT 的时候,完全不需要用子树求和的,而是可以考虑每个节点的权值对其它节点的影响。还句话说,我们可以考虑某个节点的权值如果是 \(1\),那么它会对它的所有祖先产生贡献,那就变成了链上信息维护,普通 LCT 就可以了。

Code

#include<bits/stdc++.h>
#define ll long long
#define inf (1<<30)
#define INF (1ll<<60)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mkp make_pair
#define fi first
#define se second
#define pb push_back
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define per(i,j,k) for(int i=(j);i>=(k);i--)
using namespace std;
const int MAXN=2e6+10;
struct LCT{
    struct node{int ch[2],fa,val,tag;}tr[MAXN];
    #define ls tr[x].ch[0]
    #define rs tr[x].ch[1]
    bool nroot(int x){return tr[tr[x].fa].ch[0]==x||tr[tr[x].fa].ch[1]==x;}
    void add(int x,int v){tr[x].val+=v,tr[x].tag+=v;}
    void pushdown(int x){
        if(!tr[x].tag) return;
        if(ls) add(ls,tr[x].tag);
        if(rs) add(rs,tr[x].tag);
        tr[x].tag=0;
    }
    void rot(int x){
        int f=tr[x].fa,k=(x==tr[f].ch[1]),g=tr[f].fa,v=tr[x].ch[k^1];
        if(nroot(f)) tr[g].ch[f==tr[g].ch[1]]=x;
        tr[x].ch[k^1]=f;tr[f].ch[k]=v;
        if(v) tr[v].fa=f;
        tr[f].fa=x;tr[x].fa=g;
    }int stk[MAXN],top;
    void splay(int x){
        int tmp=x;top=0;stk[++top]=tmp;
        while(nroot(tmp)) tmp=tr[tmp].fa,stk[++top]=tmp;
        while(top) pushdown(stk[top--]);
        while(nroot(x)){
            int f=tr[x].fa,g=tr[f].fa;
            if(nroot(f))
                rot((f==tr[g].ch[1])^(x==tr[f].ch[1])?x:f);
            rot(x);
        }
    }
    void access(int x){for(int s=0;x;s=x,x=tr[x].fa)splay(x),rs=s;}
    void link(int x,int y){
        tr[x].fa=y;access(y);splay(y);
        add(y,tr[x].val);
    }
    void cut(int x){
        access(x);splay(x);
        add(ls,-tr[x].val);tr[ls].fa=0;ls=0;
    }
}T;
struct SAM{int fa,len,ch[2];}tr[MAXN];
int tot=1,lst=1;
void insert(int c){
    int np=++tot,p=lst;lst=np;
    tr[np].len=tr[p].len+1;T.tr[np].val=1;
    while(p&&!tr[p].ch[c]) tr[p].ch[c]=np,p=tr[p].fa;
    if(!p) T.link(np,1),tr[np].fa=1;
    else{
        int v=tr[p].ch[c];
        if(tr[v].len==tr[p].len+1)
            T.link(np,v),tr[np].fa=v;
        else{
            int nv=++tot;tr[nv]=tr[v];
            T.link(nv,tr[nv].fa);
            tr[nv].len=tr[p].len+1;
            while(p&&tr[p].ch[c]==v) tr[p].ch[c]=nv,p=tr[p].fa;
            T.cut(v);
            tr[v].fa=tr[np].fa=nv;
            T.link(v,nv);T.link(np,nv);
        }
    }
}
string decodeWithMask(string s, int mask) {
	for (int j = 0; j < (int)s.length(); j++) {
		mask = (mask * 131 + j) % s.length();
		
		char t = s[j];
		s[j] = s[mask];
		s[mask] = t;
	}
	
	return s;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int Q;cin>>Q;
    string s;cin>>s;
    rep(i,0,(int)s.size()-1)
        insert(s[i]-'A');
    string op;
    int mask=0;
    while(Q--){
        cin>>op>>s;
        s=decodeWithMask(s,mask);
        if(op[0]=='A'){
            rep(i,0,(int)s.size()-1)
                insert(s[i]-'A');
        }
        else{
            int pt=0,p=1;
            while(pt<(int)s.size()&&tr[p].ch[s[pt]-'A'])
                p=tr[p].ch[s[pt++]-'A'];
            if(pt==(int)s.size()){
                T.splay(p);
                int res=T.tr[p].val;
                cout<<res<<'\n';mask^=res;
            }else cout<<0<<'\n';
        }
    }
    return 0;
}

标签:ch,P5212,int,tr,SubString,fa,np,define
来源: https://www.cnblogs.com/ZCETHAN/p/16181474.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有