zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj3277

    陈年老坑

    题意大概是有n个字符串,要求出每一个字符串的所有子串(不包括空串)在所有字符串(包括自身)中出现次数不少于k的有多少个。n,k,字符串总长<=100000。

    如果只有一个串的话,非常好办,直接把它建成后缀自动机就行了。

    那么不止一个串该怎么办呢?想必是也可以用后缀自动机解决的。这时就要建出一棵Trie树的后缀自动机。

     这就是广义呕吐之光后缀自动机

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #define maxn 200005
    using namespace std;
    int n,k;
    long long c[maxn];
    long long ans[maxn]; 
    struct data {
        long long son[maxn][26],link[maxn],step[maxn],last,cnt,t[maxn],size[maxn],tp[maxn];
        data() {last=cnt=1;}
        void extend(int x,int id) {
            int p=last,np=last=++cnt;step[np]=step[p]+1;t[np]=id;
            while(p&&!son[p][x]) son[p][x]=np,p=link[p];
            if(!p) link[np]=1;
            else {
                int q=son[p][x];
                if(step[q]==step[p]+1) link[np]=q;
                else {
                    int nq=++cnt;
                    memcpy(son[nq],son[q],sizeof(son[q]));
                    step[nq]=step[p]+1;
                    link[nq]=link[q];link[np]=link[q]=nq;size[nq]=size[q];tp[nq]=tp[q];
                    while(p&&son[p][x]==q) son[p][x]=nq,p=link[p];
                }
            }
            for(int i=np;i&&tp[i]!=id;i=link[i]) size[i]++,tp[i]=id;
        }
    }sam;
    int head[maxn],sum;
    struct edge {
        int to,next;
    }e[maxn];
    void add(int u,int v) {e[sum].to=v;e[sum].next=head[u];head[u]=sum++;}
    char s[maxn];
    void dfs(int x) {
        c[x]+=c[sam.link[x]];ans[sam.t[x]]+=c[x];
        for(int i=head[x];i>=0;i=e[i].next) dfs(e[i].to);
    }
    int main() {
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) {
            scanf("%s",s+1);
            int len=strlen(s+1);sam.last=1;
            for(int j=1;j<=len;j++) sam.extend(s[j]-'a',i);
        }
        for(int i=2;i<=sam.cnt;i++)    {
            add(sam.link[i],i);
            if(sam.size[i]>=k) c[i]=sam.step[i]-sam.step[sam.link[i]];
        }
        dfs(1);
        for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
    }
    /*
    3 2
    abaac
    bba
    bbacb
    */
    

      

    宣传一波电教XX,欢迎加入。

  • 相关阅读:
    973. K Closest Points to Origin
    919. Complete Binary Tree Inserter
    993. Cousins in Binary Tree
    20. Valid Parentheses
    141. Linked List Cycle
    912. Sort an Array
    各种排序方法总结
    509. Fibonacci Number
    374. Guess Number Higher or Lower
    238. Product of Array Except Self java solutions
  • 原文地址:https://www.cnblogs.com/xzyf/p/8476117.html
Copyright © 2011-2022 走看看