好久没有更blog了啊。。。
对于一个给定长度为N的字符串,求它的第K小子串是什么。
这是一个SAM的模板题。
我好弱啊这个时候才开始学SAM,才会用指针。
要维护3个东西:每个状态right集合的大小、每个状态能到达的所有状态的right集合总大小、每个状态能到达的所有状态数
我没有判-1的情况反正没有-1的数据也能过
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long const int maxn=5e5+10; int n,k,o; char s[maxn]; char cc;ll ff; template<typename T>void read(T& aa) { aa=0;ff=1; cc=getchar(); while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } struct Sam{ Sam *next[27],*par; int step;ll right,sum[2]; }pool[2*maxn],*last,*root; int tot; Sam* newnode(int step) { Sam* t=pool+(tot++); memset(t->next,0,sizeof(t->next)); t->par=NULL; t->step=step; t->right=t->sum[0]=t->sum[1]=0; return t; } void Extend(int w) { Sam *p=last; Sam *np=newnode(p->step+1);np->right=1; for(;p&&!p->next[w];p=p->par) p->next[w]=np; if(!p) np->par=root; else { Sam *q=p->next[w]; if(q->step==p->step+1) np->par=q; else { Sam *nq=newnode(p->step+1); memcpy(nq->next,q->next,sizeof(q->next)); nq->par=q->par; q->par=nq; np->par=nq; for(;p&&p->next[w]==q;p=p->par) p->next[w]=nq; } } last=np; } int c[2*maxn];Sam *sa[2*maxn]; void get_jp() { Sam *r,*t; for(r=pool+1;r!=pool+tot;++r) c[r->step]++; for(int i=1;i<=n;++i) c[i]+=c[i-1]; for(r=pool+1;r!=pool+tot;++r) sa[c[r->step]--]=r; for(int i=tot-1;i;--i) { r=sa[i]; r->sum[0]=1; r->sum[1]=r->right; t=r->par; t->right+=r->right; for(int j=0;j<26;++j) { t=r->next[j]; if(!t) continue; r->sum[0]+=t->sum[0]; r->sum[1]+=t->sum[1]; } } } void travel() { Sam *r=root,*t; while(k) { for(int i=0;i<26&&k;++i) { t=r->next[i]; if(!t) continue; if(t->sum[o]>=k) { printf("%c",i+'a'); break; } k-=t->sum[o]; } r=t; if(o==1&&k<=r->right) break; if(o==0&&k<=1) break; k-= o==0? 1 : r->right; } } int main() { scanf("%s",s+1); n=strlen(s+1); last=root=newnode(0); for(int i=1;i<=n;++i) Extend(s[i]-'a'); get_jp(); read(o); read(k); travel(); return 0; }
顺便再放一道水题(spoj8222)的代码
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long const int maxn=250000+7; int n,ans[maxn]; char s[maxn]; char cc;ll ff; template<typename T>void read(T& aa) { aa=0;ff=1; cc=getchar(); while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } struct Sam{ Sam *next[27],*par; int step,right; }pool[2*maxn],*last,*root; int tot; Sam* newnode(int step) { Sam *t=pool+(tot++); memset(t->next,0,sizeof(t->next)); t->step=step; t->right=0; return t; } void Extend(int w) { Sam *p=last; Sam *np=newnode(p->step+1); np->right=1; for(;p&&!p->next[w];p=p->par) p->next[w]=np; if(!p) np->par=root; else { Sam *q=p->next[w]; if(q->step==p->step+1) np->par=q; else { Sam *nq=newnode(p->step+1); memcpy(nq->next,q->next,sizeof(q->next)); nq->par=q->par; q->par=nq; np->par=nq; for(;p&&p->next[w]==q;p=p->par) p->next[w]=nq; } } last=np; } int c[2*maxn];Sam *sa[2*maxn]; void csort() { Sam *t; for(t=pool+1;t!=pool+tot;++t) c[t->step]++; for(int i=1;i<=n;++i) c[i]+=c[i-1]; for(t=pool+1;t!=pool+tot;++t) sa[c[t->step]--]=t; for(int i=tot-1;i;--i) { t=sa[i]; ans[t->step]=max(ans[t->step],t->right); t->par->right+=t->right; } } int main() { scanf("%s",s+1); last=root=newnode(0); n=strlen(s+1); for(int i=1;i<=n;++i) Extend(s[i]-'a'); csort(); for(int i=n;i;--i) ans[i]=max(ans[i],ans[i+1]); for(int i=1;i<=n;++i) printf("%d ",ans[i]); return 0; }