• SubString


    题目

    真是一道非常好的码农题,(SAM+LCT)

    看到查询子串出现次数我们就能想到这是一个(SAM)

    看到动态往后加入字符串我们就可以想到需要(LCT)来维护子树和

    由于(LCT)并不是很方便维护子树,所以每次加入一个点的时候只需要把根到这个点的路径上的点权加一就好了

    查询在(SAM)上匹配出位置,差一个单点权值就可以了

    别忘了加入(clone)节点的时候要继承儿子的点权

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #define maxn 1200005
    #define re register
    #define LL long long
    char S[3000005],opt[10];
    std::string chars;
    int Q,mask,ans,lst=1,cnt=1;
    int tag[maxn],rev[maxn],fa[maxn],ch[maxn][2],s[maxn],st[maxn];
    inline int nroot(int x) {return ch[fa[x]][1]==x||ch[fa[x]][0]==x;}
    void Gets(int mask) {
        scanf("%s",S);
        chars=S;
        for (int j=0;j<chars.length();j++) {
            mask=(mask*131+j)%chars.length();
            char t=chars[j];
            chars[j]=chars[mask];
            chars[mask]=t;
        }
    }
    inline void pushdown(int x) {
    	if(rev[x]) {
    		if(ch[x][0]) rev[ch[x][0]]^=1,std::swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
    		if(ch[x][1]) rev[ch[x][1]]^=1,std::swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
    		rev[x]=0;
    	}
    	if(tag[x]) {
    		if(ch[x][0]) s[ch[x][0]]+=tag[x],tag[ch[x][0]]+=tag[x];
    		if(ch[x][1]) s[ch[x][1]]+=tag[x],tag[ch[x][1]]+=tag[x];
    		tag[x]=0;
    	}
    }
    inline void rotate(int x) {
    	int y=fa[x],z=fa[y],k=ch[y][1]==x,w=ch[x][k^1];
    	if(nroot(y)) ch[z][ch[z][1]==y]=x;
    	ch[x][k^1]=y,ch[y][k]=w;
    	fa[w]=y,fa[y]=x,fa[x]=z;
    }
    inline void splay(int x) {
    	int y=x,top=0;
    	st[++top]=x;
    	while(nroot(y)) st[++top]=fa[y],y=fa[y];
    	while(top) pushdown(st[top--]);
    	while(nroot(x)) {
    		int y=fa[x];
    		if(nroot(y)) rotate((ch[fa[y]][1]==y)^(ch[y][1]==x)?x:y);
    		rotate(x);
    	}
    }
    inline void access(int x) {
    	for(re int y=0;x;y=x,x=fa[x])
    		splay(x),ch[x][1]=y;
    }
    inline void makeroot(int x) {
    	access(x);splay(x),rev[x]^=1;std::swap(ch[x][0],ch[x][1]);
    }
    inline void split(int x,int y) {
    	makeroot(x);access(y);splay(y);
    }
    inline void link(int x,int y) {
    	fa[x]=y;
    }
    inline void cut(int x,int y) {
    	split(x,y);ch[y][0]=fa[x]=0;
    }
    struct Suffix_Automata {
    	int len[maxn],fa[maxn],son[maxn][26];
    	inline void ins(int c) {
    		int p=++cnt,f=lst; lst=p;
    		len[p]=len[f]+1;
    		while(f&&!son[f][c]) son[f][c]=p,f=fa[f];
    		if(!f) {fa[p]=1;link(p,fa[p]);split(1,p);tag[p]++;s[p]++;return;}
    		int x=son[f][c];
    		if(len[f]+1==len[x]) {fa[p]=x;link(p,fa[p]);split(1,p);tag[p]++;s[p]++;return;}
    		int y=++cnt;
    		len[y]=len[f]+1,fa[y]=fa[x],cut(fa[x],x),fa[x]=fa[p]=y;
    		link(x,fa[x]),link(p,fa[p]),link(y,fa[y]);
    		splay(x);s[y]=s[x];
    		for(re int i=0;i<26;i++) son[y][i]=son[x][i];
    		while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
    		split(1,p);tag[p]++;s[p]++;
    	}
    	inline void add() {
    		Gets(mask);
    		int len=chars.length();
    		for(re int i=0;i<len;i++) ins(chars[i]-'A');
    	}
    	inline int check() {
    		Gets(mask);
    		int len=chars.length();
    		int now=1;
    		for(re int i=0;i<len;i++) {
    			now=son[now][chars[i]-'A'];
    			if(!now) break;
    		}
    		if(!now) return 0;
    		splay(now);return s[now];
    	}
    }SAM;
    int main()
    {
    	scanf("%d",&Q);
    	scanf("%s",S+1);
    	int len=strlen(S+1);
    	for(re int i=1;i<=len;i++) SAM.ins(S[i]-'A');
    	while(Q--) {
    		scanf("%s",opt);
    		if(opt[0]=='A') SAM.add();
    		else {
    			ans=SAM.check();
    			mask^=ans;
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    201771010101 白玛次仁 《2018面向对象程序设计(Java)》第十六周学习总结
    201771010101 白玛次仁 《2018面向对象程序设计(Java)》第十五周学习总结
    201771010101 白玛次仁 《2018面向对象程序设计(Java)》第十四周学习总结
    201771010101 白玛次仁 《2018面向对象程序设计(Java)》第十三周学习总结
    十三周作业
    第十三周上机作业
    第十二周作业
    第十二周上机练习
    第十一周作业
    第十一周上机练习
  • 原文地址:https://www.cnblogs.com/asuldb/p/10371328.html
Copyright © 2020-2023  润新知