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,欢迎加入。

  • 相关阅读:
    python input and output and cpickle
    NS3中文教程:3下载及编译软件
    Wireshark Display fliters
    Python 中的几种copy用法
    python func for shell operation
    关于AX的临时表
    关于AX中的Query是如何查询记录
    POJ 2996, Help Me with the Game
    POJ 1328, Radar Installation
    POJ 3295, Tautology
  • 原文地址:https://www.cnblogs.com/xzyf/p/8476117.html
Copyright © 2011-2022 走看看