zoukankan      html  css  js  c++  java
  • 字符串(AC自动机+fail tree)

    题目描述:

    题解:

    a[i] 实际就是字符串 i 在总集合中出现的次数,很自然地想到fail tree

    注意:注释中的那段代码是不能用的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int N=2000010;
    struct Edge{int v,nxt;}edge[N];
    int head[N],cnt;
    int ch[N][26],fail[N],word[N],num;
    int st[N],ed[N],tot;
    int m,l,len[N],bg[N],que,work[N];
    ll c[N],mask,ans,val[N],opt[N];
    char s[N],str[N];
    void add_edge(int u,int v){
        edge[++cnt].v=v;
        edge[cnt].nxt=head[u];
        head[u]=cnt;
    }
    void insert(char *s,int id){
        int now=0;
        for(int i=0;i<len[id];i++){
            int x=s[i]-'a';
            if(!ch[now][x]) ch[now][x]=++num;
            now=ch[now][x];
        }
        word[id]=now;
    }
    void get_fail(){
        queue<int> q;
        for(int i=0;i<26;i++){
            if(ch[0][i]) q.push(ch[0][i]);
        }
        while(!q.empty()){
            int now=q.front();
            q.pop();
            for(int i=0;i<26;i++){
                if(ch[now][i]){
                    fail[ch[now][i]]=ch[fail[now]][i];
                    q.push(ch[now][i]);
                }
                else ch[now][i]=ch[fail[now]][i];
            }
        }
    }
    void dfs(int u){
        st[u]=++tot;
        for(int i=head[u];i;i=edge[i].nxt) 
            dfs(edge[i].v);
        ed[u]=tot;
    }
    void build_fail_tree(){
        for(int i=1;i<=num;i++)
            add_edge(fail[i],i);
        dfs(0);
    }
    inline int lowbit(int x){return x&(-x);}
    void add(int x,int d){
        for(int i=x;i<=tot;i+=lowbit(i))
            c[i]+=d;
    }
    ll getsum(int x){
        ll sum=0;
        for(int i=x;i>=1;i-=lowbit(i))
            sum+=c[i];
        return sum;
    }
    void query(int l,int r){
        que++;
        int now=0;
        for(int i=l;i<=r;i++){
            now=ch[now][s[i]-'a'];
            if(work[now]==que)//子串在s中已经出现过 
                ans+=val[now];
            else{
                work[now]=que;
                //val[now]=getsum(ed[now])-getsum(st[now]-1);
                val[now]=getsum(st[now]);
                ans+=val[now];
            }
        }
    }
    int main(){
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%lld%s",&opt[i],str);
            len[i]=strlen(str);
            bg[i]=l+1;
            insert(str,i);
            for(int j=0;j<len[i];j++)
                s[++l]=str[j];
        }
        get_fail();
        build_fail_tree();
        for(int i=1;i<=m;i++){
            opt[i]^=mask;
            if(opt[i]==1){
                add(st[word[i]],1);
                add(ed[word[i]]+1,-1);
            } //add(st[word[i]],1);
            else if(opt[i]==2){
                add(st[word[i]],-1);
                add(ed[word[i]]+1,1);
            } //add(st[word[i]],-1);
            else if(opt[i]==3){
                ans=0;
                query(bg[i],bg[i]+len[i]-1);
                printf("%lld
    ",ans);
                mask^=labs(ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    HDU——1215七夕节(因数和)
    UVa——400Unix ls(字典序文本处理输出iomanip)
    廖雪峰Java5集合-3Map-Properties的使用
    python图片和字符串的转换
    廖雪峰Java5集合-3Map-1使用Map
    廖雪峰Java5集合-2List-2编写equals方法
    廖雪峰Java5集合-1Java集合简介-1Java结合简介
    廖雪峰Java4反射与泛型-3泛型-7泛型和反射
    廖雪峰Java4反射与泛型-3范型-6super通配符
    廖雪峰Java4反射与泛型-3范型-5extends通配符
  • 原文地址:https://www.cnblogs.com/HarryPotter-fan/p/11377905.html
Copyright © 2011-2022 走看看