首页 > 代码库 > Bzoj3998 [TJOI2015]弦论

Bzoj3998 [TJOI2015]弦论

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 2388  Solved: 798

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

 

Source

 

字符串 后缀自动机

T=0 除了根以外的状态都代表1个串
T=1 每个状态fail子树结束结点个数即为串的个数

也就是说如果T等于1,就用每个结点的size更新fa结点,T等于0就不更新

 1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=1000010;10 char s[mxn];11 int T;12 struct SAM{13     int t[mxn*2][26];14     int fail[mxn*2],l[mxn*2],ct[mxn*2];15     int w[mxn*2],rk[mxn*2],smm[mxn*2];16     int S,last,cnt;17     void init(){S=last=cnt=1;return;}18     void add(int c){19         int p=last,np=++cnt;20         last=np;l[np]=l[p]+1;21 //      ct[np]++;22         for(;p && !t[p][c];p=fail[p])t[p][c]=np;23         if(!p){fail[np]=S;}24         else{25             int q=t[p][c];26             if(l[q]==l[p]+1)fail[np]=q;27             else{28                 int nq=++cnt;l[nq]=l[p]+1;29                 memcpy(t[nq],t[q],sizeof t[q]);30                 fail[nq]=fail[q];31                 fail[q]=fail[np]=nq;32                 for(;p && t[p][c]==q;p=fail[p])t[p][c]=nq;33             }34         }35         return;36     }37     void st(){38         int i,j;int len=strlen(s+1),now=S;39         for(i=1;i<=cnt;i++)w[l[i]]++;40         for(i=1;i<=len;i++)w[i]+=w[i-1];41         for(i=cnt;i;i--)rk[w[l[i]]--]=i;42         for(i=1;i<=len;i++){43             now=t[now][s[i]-a];44             ct[now]++;45         }46         for(i=cnt;i;i--){47             int to=rk[i];48             if(T==1)ct[fail[to]]+=ct[to];49             else ct[to]=1;50         }51         ct[1]=0;52         for(i=cnt;i;i--){53             smm[rk[i]]=ct[rk[i]];54             for(j=0;j<26;j++){55                 smm[rk[i]]+=smm[t[rk[i]][j]];56             }57         }58         return;59     }60     void solve(int u,int k){61         if(k<=ct[u])return;62 //      printf("u:%d k:%d\n",u,k);63         k-=ct[u];64         for(int j=0;j<26;j++){65             if(t[u][j]){66                 int v=t[u][j];67                 if(k<=smm[v]){68                     printf("%c",j+a);69                     solve(v,k);70                     return;71                 }72                 else k-=smm[v];73             }74         }75         return;76     }77 }sa;78 int n,k;79 int main(){80     int i,j;81     scanf("%s",s+1);82     n=strlen(s+1);83     scanf("%d%d",&T,&k);84     sa.init();85     for(i=1;i<=n;i++) sa.add(s[i]-a);86     sa.st();87 //  printf("%d\n",sa.smm[1]);88     if(sa.smm[1]<k)printf("-1\n");89     else sa.solve(1,k);90     return 0;91 }

 

Bzoj3998 [TJOI2015]弦论