zoukankan      html  css  js  c++  java
  • bzoj3899 弦论

    好久没有更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;
    }
    

      

  • 相关阅读:
    没有上司的舞会
    邮票面值设计
    小木棍
    简单的试炼
    区间质数
    加工生产调度
    泥泞的道路
    总数统计
    中庸之道

  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8206900.html
Copyright © 2011-2022 走看看