【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);
  }
}
原文地址:https://www.cnblogs.com/shxnb666/p/11279205.html