首页 > 代码库 > Bzoj3998 [TJOI2015]弦论
Bzoj3998 [TJOI2015]弦论
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
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]弦论
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。