对于一个给定长度为N的字符串,求它的第K小子串是什么。
标签:can pair ret span math put names use enter
对于一个给定长度为N的字符串,求它的第K小子串是什么。
第一行是一个仅由小写英文字母构成的字符串S
输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1
N<=5*10^5
#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; }
标签:can pair ret span math put names use enter
原文地址:http://www.cnblogs.com/dyzll/p/7624748.html