zoukankan      html  css  js  c++  java
  • bzoj 5512

    后缀自动机基本应用

    对询问串建起后缀自动机,然后建起parent树,做一次子树统计就知道了每个节点代表的字符串出现次数

    接下来我们只考虑出现次数等于$k$的那些点,对于任意一个点$p$我们知道他代表的子串长度是连续的,长度范围在$[len_{fa}+1,len_{p}]$之间,那么我们做个差分,最后统计一次就知道每个长度出现次数了

    时间复杂度$O(n)$

    代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    struct node
    {
        int tranc[27];
        int len,pre,endpos;
    }s[200005];
    int tot,las;
    int maxans,maxp;
    int T,n,k;
    int f[200005];
    int S[200005];
    char ch[100005];
    vector <int> v[200005];
    void ins(int c)
    {
        int nwp=++tot;
        s[nwp].len=s[las].len+1;
        s[nwp].endpos=1;
        int lsp;
        for(lsp=las;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)s[lsp].tranc[c]=nwp;
        if(!lsp)s[nwp].pre=1;
        else 
        {
            int lsq=s[lsp].tranc[c];
            if(s[lsq].len==s[lsp].len+1)s[nwp].pre=lsq;
            else 
            {
                int nwq=++tot;
                s[nwq]=s[lsq];
                s[nwq].endpos=0;
                s[nwq].len=s[lsp].len+1;
                s[lsq].pre=s[nwp].pre=nwq;
                while(s[lsp].tranc[c]==lsq)s[lsp].tranc[c]=nwq,lsp=s[lsp].pre;
            }
        }
        las=nwp;
    }
    void init()
    {
        for(int i=1;i<=tot;i++)memset(s[i].tranc,0,sizeof(s[i].tranc)),s[i].len=s[i].pre=s[i].endpos=0;
        for(int i=1;i<=tot;i++)v[i].clear();
        memset(S,0,sizeof(S));
        tot=las=1;
        maxans=maxp=-0x3f3f3f3f;
    }
    void buildtree()
    {
        for(int i=2;i<=tot;i++)v[s[i].pre].push_back(i);
    }
    int query()
    {
        int maxp=-1,maxv=0;
        for(int i=1;i<=n;i++)
        {
            S[i]+=S[i-1];
            if(S[i]>=maxv&&S[i])maxv=S[i],maxp=i;
        }
        return maxp;
    }
    void dfs(int x)
    {
        for(int i=0;i<v[x].size();i++)
        {
            int to=v[x][i];
            dfs(to);
            s[x].endpos+=s[to].endpos;
        }
        if(s[x].endpos==k&&x!=1)S[s[s[x].pre].len+1]++,S[s[x].len+1]--;
    }
    void solve()
    {
        scanf("%s",ch+1);
        n=strlen(ch+1),scanf("%d",&k);
        for(int i=1;i<=n;i++)ins(ch[i]-'a'+1);
        buildtree(),dfs(1);
        printf("%d
    ",query());
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)init(),solve();
        return 0;
    }
  • 相关阅读:
    ADC测试matlab代码
    matlab的滤波器仿真——低通滤波器与插值滤波器
    PDF转Image最终方案
    多线程和蕃茄炒蛋
    git学习总结
    踩坑了,当前目录问题
    Angular 1.x 升级到 Angular 2
    打造AngularJs2.0开发环境
    发布一个自用的ansi转utf8程序
    用itextsharp打印pdf示例
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11128305.html
Copyright © 2011-2022 走看看