• 【TJOI2015】弦论


    题面

    https://www.luogu.org/problem/P3975

    题解

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define ri register int
    #define N 500050
    using namespace std;
    
    int les=0;
    char s[N];
    int n,t,k;
    
    struct SAM {
      int len[N<<1],ff[N<<1];
      int ch[N<<1][26];
      int cnt[N<<1];
      int tot,las;
      int sum[N<<1];
      int a[N<<1],ton[N<<1];
      void init() {
        tot=las=1;
      }
      void extend(int c) {
        int p=las,np=++tot; las=tot;
        len[np]=len[p]+1; cnt[np]++;
        while (p && !ch[p][c]) ch[p][c]=np,p=ff[p];
        if (!p) ff[np]=1;
        else {
          int q=ch[p][c];
          if (len[q]==len[p]+1) ff[np]=q;
          else {
            int nq=++tot;
            for (ri i=0;i<26;i++) ch[nq][i]=ch[q][i]; ff[nq]=ff[q];
            len[nq]=len[p]+1;
            ff[q]=ff[np]=nq;
            while (p && ch[p][c]==q) ch[p][c]=nq,p=ff[p];
          }
        }
      }
      
      void work() {
        for (ri i=1;i<=tot;i++) ton[len[i]]++;
        for (ri i=1;i<=tot;i++) ton[i]+=ton[i-1];
        for (ri i=1;i<=tot;i++) a[ton[len[i]]--]=i;
        for (ri i=tot;i>=1;i--) cnt[ff[a[i]]]+=cnt[a[i]];
        if (t==0) {
          for (ri i=2;i<=tot;i++) cnt[i]=1;
        }
        cnt[1]=0;
        for (ri i=1;i<=tot;i++) sum[i]=cnt[i];
        for (ri i=tot;i>=1;i--)
          for (ri j=0;j<26;j++) sum[a[i]]+=sum[ch[a[i]][j]];
      }
      
      void query(int x) {
        if (les<k && k<=les+cnt[x]) {
          return;
        }
        les+=cnt[x];
        for (ri i=0;i<26;i++) {
          if (!ch[x][i]) continue;
          les+=sum[ch[x][i]];
          if (les>=k) {
            les-=sum[ch[x][i]];
            printf("%c",'a'+i);
            query(ch[x][i]);
            return;
          }
        }
      }
    } sam;
    
    int main(){
      scanf("%s",s+1); n=strlen(s+1);
      scanf("%d %d",&t,&k);
      sam.init();
      for (ri i=1;i<=n;i++) sam.extend(s[i]-'a');
      sam.work();
      if (sam.sum[1]<k) {
        puts("-1");
      }
      else {
        les=0;
        sam.query(1);
      }
    }
  • 相关阅读:
    剑指offer51-正则表达式匹配
    剑指offer50-构建乘积数组
    剑指offer49-数组中的重复
    PHP系列笔记——Zend_Controller工作流程
    多态与重载
    读取文件数据的大概流程
    基于HTTP协议下载文件的实现
    C++中的面向对象笔记
    firebreath注册接口
    python读取excelxlsx,写入excel
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11279205.html
Copyright © 2020-2023  润新知