首页 > 代码库 > 后缀自动机

后缀自动机

BZOJ3998

#include <cstdio>
#include <cstring>
using namespace std;

  int last,dis[1000011],fa[1000011],a[1000011][26],cnt,sum[1000011];
  int val[1000011],n,dl[1000011],T,k;
  char st[1000011];

  void ins(int num){
      int p=last,np=last=++cnt;
      dis[np]=dis[p]+1;val[np]=1;
      while (!a[p][num]&&p) a[p][num]=np,p=fa[p];
      if (!p) fa[np]=1;else{
        int q=a[p][num];
        if (dis[p]+1==dis[q]) fa[np]=q;else{
          int nq=++cnt;dis[nq]=dis[p]+1;
        memcpy(a[nq],a[q],sizeof(a[q]));
        fa[nq]=fa[q];
        fa[q]=fa[np]=nq;
        while (a[p][num]==q) a[p][num]=nq,p=fa[p];
      }
    }
  }

  void init(){
       for (int i=1;i<=cnt;i++) sum[dis[i]]++;
      for (int i=1;i<=n;i++) sum[i+1]+=sum[i];
      for (int i=cnt;i>0;i--) dl[sum[dis[i]]--]=i;
      for (int i=1;i<=cnt;i++) sum[i]=0;
      
      for (int i=cnt;i>0;i--){
        int t=dl[i];
      if (T==1) val[fa[t]]+=val[t];else val[t]=1;
    }
    val[1]=0;
    for (int i=cnt;i>0;i--){
      int t=dl[i];sum[t]=val[t];
      for (int j=0;j<26;j++)
        sum[t]+=sum[a[t][j]];
    }
  }

  void dfs(int po,int num){
      if (num<=val[po]) return;
      num-=val[po];
      for (int i=0;i<26;i++)
        if (a[po][i]){
          if (num<=sum[a[po][i]]){
            putchar(a+i);
          dfs(a[po][i],num);
          return;    
        }
        num-=sum[a[po][i]];
      }
  }

  int main(){
      scanf("%s",&st);
      scanf("%d%d",&T,&k);
      
      last=cnt=1;dis[1]=1;n=strlen(st);
      for (int i=0;i<n;i++)
        ins(st[i]-a);
        
      init();
      
      if (k>sum[1]) printf("-1\n");else dfs(1,k);
  }

 

后缀自动机