数据结构模板(循环队列,优先级队列,树状数组,线段树,哈希,后缀数组)--zhengjun

循环队列

template<typename item,const int _size>
class cirqueue{
    private:
        item q[_size];
        int head,tail;
        int len;
    public:
        cirqueue(){
        	memset(q,0,sizeof(q));
        	head=tail=len=0;
		}
        void push(item const &x){
        	q[tail]=x;
        	len++;
        	tail=(tail+1)%_size;
		}
        void pop(){
        	head=(head+1)%_size;
        	len--;
		}
        item front()const{
        	return q[head];
		}
        int size()const{
        	return len;
		}
        bool empty()const{
        	return len==0;
		}
		item back()const{
			return q[tail];
		}
};

优先级队列

template<typename item,const int _size,bool (*check)(const item&,const item&)>
class prioqueue{
	#define ss(x,y) check(q[x],q[y])
	private:
		item q[_size+1];
		int len;
		void swp(const int &x,const int &y){
			item k=q[x];
			q[x]=q[y];
			q[y]=k;
		}
	public:
		prioqueue(){
			memset(q,0,sizeof(q));
			len=0;
		}
		void push(const item &x){
			q[++len]=x;
			int now=len;
			while(now>1&&!ss(now>>1,now)){
				swp(now,now>>1);
				now>>=1;
			}
		}
		void pop(){
			q[1]=q[len--];
			int now=1;
			while((now<<1)<=len){
				if((now<<1|1)<=len){
					if(ss(now,now<<1)&&ss(now,now<<1|1))break;
					if(ss(now<<1,now<<1|1))swp(now,now<<1),now<<=1;
					else swp(now,now<<1|1),now=now<<1|1;
				}
				else{
					if(ss(now<<1,now))
						swp(now,now<<1);
					break;
				}
			}
		}
		item top()const{
			return q[1];
		}
		bool empty()const{
			return len==0;
		}
		int size()const{
			return len;
		}
	#undef ss
};

树状数组

template<typename item,const int _size>
class sum_treearray{
	private:
		item c[_size+1];
	public:
		sum_treearray(){
			memset(c,0,sizeof(c));
		}
		void update(int i,item x){
			for(;i<=_size;i+=i&-i)c[i]+=x;
		}
		item query(int i){
			item sum=0;
			for(;i>0;i-=i&-i)sum+=c[i];
			return sum;
		}
		item query(int i,int j){
			return query(j)-query(i-1);
		}
};
template<typename item,const int _size,item (*add)(const item&,const item&)>
class treearray{
	private:
		item c[_size+1];
	public:
		treearray(){
			memset(c,0,sizeof(c));
		}
		void update(int i,item x){
			item last;
			c[i]+=x;
			last=c[i];
			for(i=i+(i&-i);i<=_size;i+=(i&-i))c[i]=add(c[i],last),last=c[i];
		}
		item query(int i){
			item sum=c[i];
			for(i=i-(i&-i);i>0;i-=(i&-i))sum=add(sum,c[i]);
			return sum;
		}
};

线段树

template<typename item,const int _size>
class sum_linetree{
	private:
		item tree[_size<<2],f[_size<<2];
		void up(int rt){
			tree[rt]=tree[rt<<1]+tree[rt<<1|1];
		}
		void down(int l,int r,int rt){
			if(f[rt]>0){
				tree[rt<<1]+=f[rt]*l;
				tree[rt<<1|1]+=f[rt]*r;
				f[rt<<1]+=f[rt];
				f[rt<<1|1]+=f[rt];
				f[rt]=0;
			}
		}
		void buildadd(item *a,int l,int r,int rt){
			if(l==r){
				tree[rt]=a[l];
				return;
			}
			int m=(l+r)>>1;
			buildadd(a,l,m,rt<<1);
			buildadd(a,m+1,r,rt<<1|1);
			up(rt);
		}
		void updateadd(int head,int tail,item x,int l,int r,int rt){
			if(head<=l&&r<=tail){
				tree[rt]+=x;
				f[rt]+=x;
				return;
			}
			int m=(l+r)>>1;
			down(m-l+1,r-m,rt);
			if(head<=m)updateadd(head,tail,x,l,m,rt<<1);
			if(m+1<=tail)updateadd(head,tail,x,m+1,r,rt<<1|1);
			up(rt);
		}
		item queryadd(int head,int tail,int l,int r,int rt){
			if(head<=l&&r<=tail){
				return tree[rt];
			}
			int m=(l+r)>>1;
			down(m-l+1,r-m,rt);
			item sum=0;
			if(head<=m)sum+=queryadd(head,tail,l,m,rt<<1);
			if(m+1<=tail)sum+=queryadd(head,tail,m+1,r,rt<<1|1);
			return sum;
		}
	public:
		sum_linetree(){
			memset(tree,0,sizeof(tree));
			memset(f,0,sizeof(f));
		}
		void build(item *a){
			buildadd(a,1,_size,1);
		}
		void update(int head,int tail,item x){
			updateadd(head,tail,x,1,_size,1);
		}
		item query(int head,int tail){
			return queryadd(head,tail,1,_size,1);
		}
};
template<typename item,const int _size,item (*add)(const item&,const item&)>
class linetree{
	private:
		item tree[_size<<2],f[_size<<2];
		void up(int rt){
			tree[rt]=add(tree[rt<<1],tree[rt<<1|1]);
		}
		void down(int rt){
			if(f[rt]>0){
				tree[rt<<1]+=f[rt];
				tree[rt<<1|1]+=f[rt];
				f[rt<<1]+=f[rt];
				f[rt<<1|1]+=f[rt];
				f[rt]=0;
			}
		}
		void buildadd(item *a,int l,int r,int rt){
			if(l==r){
				tree[rt]=a[l];
				return;
			}
			int m=(l+r)>>1;
			buildadd(a,l,m,rt<<1);
			buildadd(a,m+1,r,rt<<1|1);
			up(rt);
		}
		void updateadd(int head,int tail,item x,int l,int r,int rt){
			if(head<=l&&r<=tail){
				tree[rt]+=x;
				f[rt]+=x;
				return;
			}
			int m=(l+r)>>1;
			down(rt);
			if(head<=m)updateadd(head,tail,x,l,m,rt<<1);
			if(m+1<=tail)updateadd(head,tail,x,m+1,r,rt<<1|1);
			up(rt);
		}
		item queryadd(int head,int tail,int l,int r,int rt){
			if(head<=l&&r<=tail){
				return tree[rt];
			}
			int m=(l+r)>>1;
			down(rt);
			if(head<=m&&m+1<=tail)return add(queryadd(head,tail,l,m,rt<<1),queryadd(head,tail,m+1,r,rt<<1|1));
			if(head<=m)return queryadd(head,tail,l,m,rt<<1);
			return queryadd(head,tail,m+1,r,rt<<1|1);
		}
	public:
		linetree(){
			memset(tree,0,sizeof(tree));
			memset(f,0,sizeof(f));
		}
		void build(item *a){
			buildadd(a,1,_size,1);
		}
		void update(int head,int tail,item x){
			updateadd(head,tail,x,1,_size,1);
		}
		item query(int head,int tail){
			return queryadd(head,tail,1,_size,1);
		}
};

哈希

template<typename item,int _size>
class open_hash{
	private:
		item f[_size];
		int g[_size];
		int change(int x){
			return x%_size;
		}
		int change(long long x){
			return x%_size;
		}
		int change(char x[]){
			int kk=0;
			for(int i=0;i<strlen(x);i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(string x){
			int kk=0;
			for(int i=0;i<x.length();i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(double x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
		int change(float x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
	public:
		open_hash(){
			memset(f,0,sizeof(f));
			memset(g,0,sizeof(g));
		}
		void add(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			f[pos]=x;
			g[pos]++;
		}
		int get(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			return g[pos];
		}
};
template<typename item,int _size,int (*change)(item)>
class self_open_hash{
	private:
		item f[_size];
		int g[_size];
	public:
		self_open_hash(){
			memset(f,0,sizeof(f));
			memset(g,0,sizeof(g));
		}
		void add(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			f[pos]=x;
			g[pos]++;
		}
		int get(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			return g[pos];
		}
};
template<typename item,int _size>
class list_hash{
	private:
		item a[_size];
		int nex[_size],head[_size],k,g[_size];
		int change(int x){
			return x%_size;
		}
		int change(long long x){
			return x%_size;
		}
		int change(char x[]){
			int kk=0;
			for(int i=0;i<strlen(x);i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(string x){
			int kk=0;
			for(int i=0;i<x.length();i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(double x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
		int change(float x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
	public:
		list_hash(){
			memset(a,0,sizeof(a));
			memset(nex,0,sizeof(nex));
			memset(head,-1,sizeof(head));
			memset(g,0,sizeof(g));
			k=0;
		}
		void add(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=-1){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==-1){
				a[k]=x;
				g[k]=1;
				nex[k]=head[pos];
				head[pos]=k++;
			}
			else g[now]++;
		}
		int get(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=-1){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==-1)return -1;
			return g[now];
		}
};
template<typename item,int _size,int (*change)(item)>
class self_list_hash{
	private:
		item a[_size];
		int nex[_size],head[_size],k,g[_size];
	public:
		self_list_hash(){
			memset(a,0,sizeof(a));
			memset(nex,0,sizeof(nex));
			memset(head,-1,sizeof(head));
			memset(g,0,sizeof(g));
			k=0;
		}
		void add(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=-1){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==-1){
				a[k]=x;
				g[k]=1;
				nex[k]=head[pos];
				head[pos]=k++;
			}
			else g[now]++;
		}
		int get(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=0){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==0)return -1;
			return g[now];
		}
};

总和

template<typename item,const int _size>
class cirqueue{
    private:
        item q[_size];
        int head,tail;
        int len;
    public:
        cirqueue(){
        	memset(q,0,sizeof(q));
        	head=tail=len=0;
		}
        void push(item const &x){
        	q[tail]=x;
        	len++;
        	tail=(tail+1)%_size;
		}
        void pop(){
        	head=(head+1)%_size;
        	len--;
		}
        item front()const{
        	return q[head];
		}
        int size()const{
        	return len;
		}
        bool empty()const{
        	return len==0;
		}
		item back()const{
			return q[tail];
		}
};
template<typename item,const int _size,bool (*check)(const item&,const item&)>
class prioqueue{
	#define check(x,y) check(q[x],q[y])
	private:
		item q[_size+1];
		int len;
		void swp(const int &x,const int &y){
			item k=q[x];
			q[x]=q[y];
			q[y]=k;
		}
	public:
		prioqueue(){
			memset(q,0,sizeof(q));
			len=0;
		}
		void push(const item &x){
			q[++len]=x;
			int now=len;
			while(now>1&&!check(now>>1,now)){
				swp(now,now>>1);
				now>>=1;
			}
		}
		void pop(){
			q[1]=q[len--];
			int now=1;
			while((now<<1)<=len){
				if((now<<1|1)<=len){
					if(check(now,now<<1)&&check(now,now<<1|1))break;
					if(check(now<<1,now<<1|1))swp(now,now<<1),now<<=1;
					else swp(now,now<<1|1),now=now<<1|1;
				}
				else{
					if(check(now<<1,now))
						swp(now,now<<1);
					break;
				}
			}
		}
		item top()const{
			return q[1];
		}
		bool empty()const{
			return len==0;
		}
		int size()const{
			return len;
		}
};
template<typename item,const int _size>
class sum_treearray{
	private:
		item c[_size+1];
	public:
		sum_treearray(){
			memset(c,0,sizeof(c));
		}
		void update(int i,item x){
			for(;i<=_size;i+=i&-i)c[i]+=x;
		}
		item query(int i){
			item sum=0;
			for(;i>0;i-=i&-i)sum+=c[i];
			return sum;
		}
		item query(int i,int j){
			return query(j)-query(i-1);
		}
};
template<typename item,const int _size,item (*add)(const item&,const item&)>
class treearray{
	private:
		item c[_size+1];
	public:
		treearray(){
			memset(c,0,sizeof(c));
		}
		void update(int i,item x){
			item last;
			c[i]+=x;
			last=c[i];
			for(i=i+(i&-i);i<=_size;i+=(i&-i))c[i]=add(c[i],last),last=c[i];
		}
		item query(int i){
			item sum=c[i];
			for(i=i-(i&-i);i>0;i-=(i&-i))sum=add(sum,c[i]);
			return sum;
		}
};
template<typename item,const int _size>
class sum_linetree{
	private:
		item tree[_size<<2],f[_size<<2];
		void up(int rt){
			tree[rt]=tree[rt<<1]+tree[rt<<1|1];
		}
		void down(int l,int r,int rt){
			if(f[rt]>0){
				tree[rt<<1]+=f[rt]*l;
				tree[rt<<1|1]+=f[rt]*r;
				f[rt<<1]+=f[rt];
				f[rt<<1|1]+=f[rt];
				f[rt]=0;
			}
		}
		void buildadd(item *a,int l,int r,int rt){
			if(l==r){
				tree[rt]=a[l];
				return;
			}
			int m=(l+r)>>1;
			buildadd(a,l,m,rt<<1);
			buildadd(a,m+1,r,rt<<1|1);
			up(rt);
		}
		void updateadd(int head,int tail,item x,int l,int r,int rt){
			if(head<=l&&r<=tail){
				tree[rt]+=x;
				f[rt]+=x;
				return;
			}
			int m=(l+r)>>1;
			down(m-l+1,r-m,rt);
			if(head<=m)updateadd(head,tail,x,l,m,rt<<1);
			if(m+1<=tail)updateadd(head,tail,x,m+1,r,rt<<1|1);
			up(rt);
		}
		item queryadd(int head,int tail,int l,int r,int rt){
			if(head<=l&&r<=tail){
				return tree[rt];
			}
			int m=(l+r)>>1;
			down(m-l+1,r-m,rt);
			item sum=0;
			if(head<=m)sum+=queryadd(head,tail,l,m,rt<<1);
			if(m+1<=tail)sum+=queryadd(head,tail,m+1,r,rt<<1|1);
			return sum;
		}
	public:
		sum_linetree(){
			memset(tree,0,sizeof(tree));
			memset(f,0,sizeof(f));
		}
		void build(item *a){
			buildadd(a,1,_size,1);
		}
		void update(int head,int tail,item x){
			updateadd(head,tail,x,1,_size,1);
		}
		item query(int head,int tail){
			return queryadd(head,tail,1,_size,1);
		}
};
template<typename item,const int _size,item (*add)(const item&,const item&)>
class linetree{
	private:
		item tree[_size<<2],f[_size<<2];
		void up(int rt){
			tree[rt]=add(tree[rt<<1],tree[rt<<1|1]);
		}
		void down(int rt){
			if(f[rt]>0){
				tree[rt<<1]+=f[rt];
				tree[rt<<1|1]+=f[rt];
				f[rt<<1]+=f[rt];
				f[rt<<1|1]+=f[rt];
				f[rt]=0;
			}
		}
		void buildadd(item *a,int l,int r,int rt){
			if(l==r){
				tree[rt]=a[l];
				return;
			}
			int m=(l+r)>>1;
			buildadd(a,l,m,rt<<1);
			buildadd(a,m+1,r,rt<<1|1);
			up(rt);
		}
		void updateadd(int head,int tail,item x,int l,int r,int rt){
			if(head<=l&&r<=tail){
				tree[rt]+=x;
				f[rt]+=x;
				return;
			}
			int m=(l+r)>>1;
			down(rt);
			if(head<=m)updateadd(head,tail,x,l,m,rt<<1);
			if(m+1<=tail)updateadd(head,tail,x,m+1,r,rt<<1|1);
			up(rt);
		}
		item queryadd(int head,int tail,int l,int r,int rt){
			if(head<=l&&r<=tail){
				return tree[rt];
			}
			int m=(l+r)>>1;
			down(rt);
			if(head<=m&&m+1<=tail)return add(queryadd(head,tail,l,m,rt<<1),queryadd(head,tail,m+1,r,rt<<1|1));
			if(head<=m)return queryadd(head,tail,l,m,rt<<1);
			return queryadd(head,tail,m+1,r,rt<<1|1);
		}
	public:
		linetree(){
			memset(tree,0,sizeof(tree));
			memset(f,0,sizeof(f));
		}
		void build(item *a){
			buildadd(a,1,_size,1);
		}
		void update(int head,int tail,item x){
			updateadd(head,tail,x,1,_size,1);
		}
		item query(int head,int tail){
			return queryadd(head,tail,1,_size,1);
		}
};
template<typename item,int _size>
class open_hash{
	private:
		item f[_size];
		int g[_size];
		int change(int x){
			return x%_size;
		}
		int change(long long x){
			return x%_size;
		}
		int change(char x[]){
			int kk=0;
			for(int i=0;i<strlen(x);i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(string x){
			int kk=0;
			for(int i=0;i<x.length();i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(double x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
		int change(float x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
	public:
		open_hash(){
			memset(f,0,sizeof(f));
			memset(g,0,sizeof(g));
		}
		void add(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			f[pos]=x;
			g[pos]++;
		}
		int get(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			return g[pos];
		}
};
template<typename item,int _size,int (*change)(item)>
class self_open_hash{
	private:
		item f[_size];
		int g[_size];
	public:
		self_open_hash(){
			memset(f,0,sizeof(f));
			memset(g,0,sizeof(g));
		}
		void add(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			f[pos]=x;
			g[pos]++;
		}
		int get(const item &x){
			int pos=change(x);
			while(g[pos]){
				if(f[pos]==x)break;
				pos=(pos+1)%_size;
			}
			return g[pos];
		}
};
template<typename item,int _size>
class list_hash{
	private:
		item a[_size];
		int nex[_size],head[_size],k,g[_size];
		int change(int x){
			return x%_size;
		}
		int change(long long x){
			return x%_size;
		}
		int change(char x[]){
			int kk=0;
			for(int i=0;i<strlen(x);i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(string x){
			int kk=0;
			for(int i=0;i<x.length();i++)kk=((long long)kk*128%_size+(int)x[i])%_size;
			return kk;
		}
		int change(double x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
		int change(float x){
			int kk;
			if(x>_size)kk=(int)x-(int)(x/_size)*x;
			else x=(long long)((long long)(x)%_size*x)%_size,kk=(int)x-(int)(x/_size)*x;
			return kk;
		}
	public:
		list_hash(){
			memset(a,0,sizeof(a));
			memset(nex,0,sizeof(nex));
			memset(head,-1,sizeof(head));
			memset(g,0,sizeof(g));
			k=0;
		}
		void add(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=-1){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==-1){
				a[k]=x;
				g[k]=1;
				nex[k]=head[pos];
				head[pos]=k++;
			}
			else g[now]++;
		}
		int get(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=-1){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==-1)return -1;
			return g[now];
		}
};
template<typename item,int _size,int (*change)(item)>
class self_list_hash{
	private:
		item a[_size];
		int nex[_size],head[_size],k,g[_size];
	public:
		self_list_hash(){
			memset(a,0,sizeof(a));
			memset(nex,0,sizeof(nex));
			memset(head,-1,sizeof(head));
			memset(g,0,sizeof(g));
			k=0;
		}
		void add(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=-1){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==-1){
				a[k]=x;
				g[k]=1;
				nex[k]=head[pos];
				head[pos]=k++;
			}
			else g[now]++;
		}
		int get(const item &x){
			int pos=change(x),now=head[pos];
			while(now!=0){
				if(a[now]==x)break;
				now=nex[now];
			}
			if(now==0)return -1;
			return g[now];
		}
};
struct suffix{
	char a[maxn];
	int n,m,sa[maxn],rank[maxn],cnt[maxn],height[maxn],f[maxn][15],lg[maxn];
	struct zj{
		int x,y,i;
	}data[maxn],tmp[maxn];
	void getsa(){
		register int i,len;
		n=strlen(a+1);m=128;
    	memset(cnt,0,sizeof(cnt));
    	memset(height,0,sizeof(height));
    	memset(sa,0,sizeof(sa));
    	memset(rank,0,sizeof(rank));
		for(i=1;i<=n;i++)data[i]=tmp[i]=(zj){0,0,0};
		for(i=1;i<=n;i++)cnt[a[i]]=1;
		for(i=2;i<=m;i++)cnt[i]+=cnt[i-1];
		for(i=n;i>=1;i--)rank[i]=cnt[a[i]];
		for(len=1;len<n;len<<=1){
			for(i=1;i<=n;i++)data[i]=(zj){rank[i],rank[i+len],i};
			memset(cnt,0,sizeof(cnt));
			for(i=1;i<=n;i++)cnt[data[i].y]++;
			for(i=1;i<=m;i++)cnt[i]+=cnt[i-1];
			for(i=n;i>=1;i--)tmp[cnt[data[i].y]--]=data[i];
			memset(cnt,0,sizeof(cnt));
			for(i=1;i<=n;i++)cnt[data[i].x]++;
			for(i=1;i<=m;i++)cnt[i]+=cnt[i-1];
			for(i=n;i>=1;i--)data[cnt[tmp[i].x]--]=tmp[i];
			for(i=1;i<=n;i++){
				if(data[i].x==data[i-1].x&&data[i].y==data[i-1].y)rank[data[i].i]=rank[data[i-1].i];
				else rank[data[i].i]=rank[data[i-1].i]+1;
			}
			if(rank[data[n].i]==n)break;
			m=rank[data[n].i];
		}
		for(i=1;i<=n;i++)sa[rank[i]]=i;
	}
	void getheight(){
		int k=0;
		for(int i=1;i<=n;i++){
			if(k)k--;
			while(i+k<=n&&sa[rank[i]-1]+k<=n&&a[i+k]==a[sa[rank[i]-1]+k])k++;
			height[rank[i]]=k;
		}
	}
	void getst(){
		lg[1]=0;
		for(int i=2;i<=n;i++)lg[i]=lg[i/2]+1;
		for(int i=1;i<=n;i++)f[i-1][1]=height[i];
		for(int j=2;(1<<j)<=n;j++){
			for(int i=1;i+(1<<j)-1<=n;i++){
				f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
			}
		}
	}
	int lcp(int l,int r){
		if(l==r)return n-l+1;
		l=rank[l];r=rank[r];
		if(l>r)swap(l,r);
		int k=lg[r-l+1];
		return min(f[l][k],f[r-(1<<k)+1][k]);
	}
};

后缀数组

struct suffix{
	char a[maxn];
	int n,sa[maxn],rank[maxn],cnt[maxn],height[maxn],f[maxn][15],lg[maxn];
	struct zj{
		int x,y,i;
		
	}data[maxn],tmp[maxn];
	void getsa(){
		register int i,len;
		n=strlen(a+1);
    	memset(cnt,0,sizeof(cnt));
    	memset(height,0,sizeof(height));
    	memset(sa,0,sizeof(sa));
    	memset(rank,0,sizeof(rank));
		for(i=1;i<=n;i++)data[i]=tmp[i]=(zj){0,0,0};
		for(i=1;i<=n;i++)cnt[a[i]]=1;
		for(i=1;i<=128;i++)cnt[i]+=cnt[i-1];
		for(i=n;i>=1;i--)rank[i]=cnt[a[i]];
		for(len=1;len<n;len<<=1){
			for(i=1;i<=n;i++)data[i]=(zj){rank[i],rank[i+len],i};
			memset(cnt,0,sizeof(cnt));
			for(i=1;i<=n;i++)cnt[data[i].y]++;
			for(i=1;i<=n;i++)cnt[i]+=cnt[i-1];
			for(i=n;i>=1;i--)tmp[cnt[data[i].y]--]=data[i];
			memset(cnt,0,sizeof(cnt));
			for(i=1;i<=n;i++)cnt[data[i].x]++;
			for(i=1;i<=n;i++)cnt[i]+=cnt[i-1];
			for(i=n;i>=1;i--)data[cnt[tmp[i].x]--]=tmp[i];
			for(i=1;i<=n;i++){
				if(data[i].x==data[i-1].x&&data[i].y==data[i-1].y)rank[data[i].i]=rank[data[i-1].i];
				else rank[data[i].i]=rank[data[i-1].i]+1;
			}
			if(rank[data[n].i]==n)break;
		}
		for(i=1;i<=n;i++)sa[rank[i]]=i;
	}
	void getheight(){
		int k=0;
		for(int i=1;i<=n;i++){
			if(k)k--;
			while(i+k<=n&&sa[rank[i]-1]+k<=n&&a[i+k]==a[sa[rank[i]-1]+k])k++;
			height[rank[i]]=k;
		}
	}
	void getst(){
		lg[1]=0;
		for(int i=2;i<=n;i++)lg[i]=lg[i/2]+1;
		for(int i=1;i<=n;i++)f[i-1][1]=height[i];
		for(int j=2;(1<<j)<=n;j++){
			for(int i=1;i+(1<<j)-1<=n;i++){
				f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
			}
		}
	}
	int lcp(int l,int r){
		if(l==r)return n-l+1;
		l=rank[l];r=rank[r];
		if(l>r)swap(l,r);
		int k=lg[r-l+1];
		return min(f[l][k],f[r-(1<<k)+1][k]);
	}
};
posted @ 2022-06-11 15:06  A_zjzj  阅读(24)  评论(0编辑  收藏  举报