zoukankan      html  css  js  c++  java
  • bzoj 3998 弦论 —— 后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998

    关于相同子串算一个还是算多个,其实就是看一种状态的 right 集合是否加上 Parent 树中子树的 right 集合;

    虽然是子串却不管 l 数组,因为实际上 dfs 走到一个点,得到的是一个确定的子串,而这个子串的状态属于这个点表示的状态,l 数组是这个点表示的状态数,当然不用考虑;

    记一个 sum 表示这个状态往后加字母能得到的所有子串个数,然后在SAM上按字典序 dfs ,走过的边就是添加的字符。

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const xn=5e5+5;
    int T,K,fa[xn<<1],l[xn<<1],go[xn<<1][30],lst=1,cnt=1,siz[xn<<1],sum[xn<<1];
    int tax[xn<<1],t[xn<<1];
    char s[xn];
    void add(int w)
    {
      int p=lst,np=++cnt; lst=np; l[np]=l[p]+1; siz[np]=1;
      for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
      if(!p)fa[np]=1;
      else
        {
          int q=go[p][w];
          if(l[q]==l[p]+1)fa[np]=q;
          else
        {
          int nq=++cnt; l[nq]=l[p]+1;
          memcpy(go[nq],go[q],sizeof go[q]);
          fa[nq]=fa[q]; fa[q]=fa[np]=nq;
          for(;go[p][w]==q;p=fa[p])go[p][w]=nq;
        }
        }
    }
    void Tsort()
    {
      for(int i=1;i<=cnt;i++)tax[l[i]]++;
      for(int i=1;i<=cnt;i++)tax[i]+=tax[i-1];
      for(int i=1;i<=cnt;i++)t[tax[l[i]]--]=i;
      for(int i=cnt;i;i--)
        {
          int x=t[i];
          if(T==0)siz[x]=1;
          else siz[fa[x]]+=siz[x];
        }
      siz[1]=0;//
      for(int i=cnt;i;i--)
        {
          int x=t[i]; sum[x]=siz[x];
          for(int j=0;j<26;j++)
        if(go[x][j])sum[x]+=sum[go[x][j]];
        }
    }
    void dfs(int x,int s)
    {
      if(s<=siz[x])return;//<=
      s-=siz[x];
      for(int j=0;j<26;j++)
        {
          if(!go[x][j])continue;
          if(s>sum[go[x][j]])s-=sum[go[x][j]];
          else
        {
          putchar(j+'a');
          dfs(go[x][j],s);
          return;
        }
        }
    }
    int main()
    {
      scanf("%s",s+1); int n=strlen(s+1);
      scanf("%d%d",&T,&K);
      for(int i=1;i<=n;i++)add(s[i]-'a');
      Tsort(); dfs(1,K); puts("");
      return 0;
    }
  • 相关阅读:
    Regexp:教程
    Regexp:目录
    笔记-C#:C# 方法、属性杂项-01
    Regexp:正则表达式应用——实例应用
    正则表达式:百科
    Regexp:template
    AngularJS:参考手册
    命令目录
    java实现连续数的公倍数
    java实现连续数的公倍数
  • 原文地址:https://www.cnblogs.com/Zinn/p/10109375.html
Copyright © 2011-2022 走看看