1. 程式人生 > >[TJOI2015]弦論

[TJOI2015]弦論

tput 第k小 http str scrip back stack air 輸出

[TJOI2015]弦論

Time Limit: 10 Sec Memory Limit: 256 MB
[Submit][Status][Discuss]

Description

對於一個給定長度為N的字符串,求它的第K小子串是什麽。

Input

第一行是一個僅由小寫英文字母構成的字符串S

第二行為兩個整數T和K,T為0則表示不同位置的相同子串算作一個。T=1則表示不同位置的相同子串算作多個。K的意義如題所述。

Output

輸出僅一行,為一個數字串,為第K小的子串。如果子串數目不足K個,則輸出-1

Sample Input

aabc
0 3

Sample Output

aab

HINT

N<=5*10^5


T<2
K<=10^9 分析:第K小字符串,可重或者不重;    對於可重,直接累加後繼個數;    對於不重,每個狀態標記為1個即可;    然後dfs搜索答案即可; 代碼:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include 
<climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define
inf 0x3f3f3f3f #define mod 1000000007 #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls (rt<<1) #define rs (rt<<1|1) #define all(x) x.begin(),x.end() const int maxn=1e6+10; const int N=5e4+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;} int n,m,k,t; struct samnode{ samnode *son[26] , *f; int l , now, sc; }*root,*last,sam[maxn],*b[maxn]; int cnt,num[maxn]; char a[maxn],ret[maxn]; void init(){ root = last = &sam[cnt=0]; } void add(int x) { samnode *p = &sam[++cnt] , *jp=last; p->l = jp->l+1; last = p; for( ; jp&&!jp->son[x] ; jp=jp->f) jp->son[x]=p; if(!jp) p->f = root; else{ if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x]; else{ samnode *r = &sam[++cnt] , *q = jp->son[x]; *r = *q; r->l = jp->l+1; q->f = p->f = r; for( ; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r; } } } int main(){ int i,j; init(); scanf("%s%d%d",a,&t,&k); int len=strlen(a); rep(i,0,len-1)add(a[i]-a); samnode *go=root; rep(i,0,len-1)go=go->son[a[i]-a],go->now=1; rep(i,0,cnt)num[sam[i].l]++; rep(i,1,len)num[i]+=num[i-1]; rep(i,0,cnt)b[--num[sam[i].l]]=&sam[i]; if(!t)rep(i,1,cnt)sam[i].now=1; if(t)for(i=cnt;i>=1;i--)b[i]->f->now+=b[i]->now; b[0]->sc=b[0]->now=0; for(i=cnt;i>=0;i--) { b[i]->sc=b[i]->now; rep(j,0,25)if(b[i]->son[j])b[i]->sc+=b[i]->son[j]->sc; } if(b[0]->sc<k) { puts("-1"); return 0; } go=root; int tot=0; while(k>0) { rep(i,0,25) { if(go->son[i]) { if(go->son[i]->sc>=k) { ret[++tot]=i+a; k-=go->son[i]->now; go=go->son[i]; break; } else k-=go->son[i]->sc; } } } ret[++tot]=0; printf("%s\n",ret+1); return 0; }

[TJOI2015]弦論