板子

splay

/*************************************************************************
    > File Name: splay.cpp
    > Author: typedef
    > Mail: 1815979752@qq.com 
    > Created Time: 2021/2/13 19:55:00
 ************************************************************************/
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,m;
struct Node{
	int s[2],p,v;//son parent 编号
	int size,flag;
	void init(int _v,int _p){
		v=_v,p=_p;
		size=1;
	}
}tr[N];
int root,idx;
void pushup(int x){
	tr[x].size=tr[tr[x].s[0]].size+tr[tr[x].s[1]].size+1;
}
void pushdown(int x){
	if(tr[x].flag){
		swap(tr[x].s[0],tr[x].s[1]);
		tr[tr[x].s[0]].flag^=1;
		tr[tr[x].s[1]].flag^=1;
		tr[x].flag=0;
	}
	return;
}
void output(int u){
	pushdown(u);
	if(tr[u].s[0]) output(tr[u].s[0]);
	if(tr[u].v>=1&&tr[u].v<=n) printf("%d ",tr[u].v);
	if(tr[u].s[1]) output(tr[u].s[1]);
	return;
}
void rotate(int x){
	//zig zag combine
	int y=tr[x].p,z=tr[y].p;
	int k=(tr[y].s[1]==x);
	//k=0右旋
	tr[z].s[tr[z].s[1]==y]=x,tr[x].p=z;
	tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y;
	tr[x].s[k^1]=y,tr[y].p=x;
	pushup(y),pushup(x);
}
void splay(int x,int k){
	while(tr[x].p!=k){
		int y=tr[x].p,z=tr[y].p;
		if(z!=k)
			if((tr[y].s[1]==x)^(tr[z].s[1]==y)) rotate(x);// 折线
			else rotate(y);
		rotate(x);
	}
	if(!k) root=x;
}
void insert(int v){
	int u=root,p=0;
	while(u) p=u,u=tr[u].s[v>tr[u].v];//自动判断了插左还是插右
	u=++idx;
	if(p) tr[p].s[v>tr[p].v]=u;
	tr[u].init(v,p);
	splay(u,0);//记得把这个点转到根
}
int get_k(int k){
	int u=root;
	while(true){
		pushdown(u);
		if(tr[tr[u].s[0]].size>=k) u=tr[u].s[0];//跳多了,回到左儿子
		else if(tr[tr[u].s[0]].size+1==k) return u;//刚刚好
		else k-=tr[tr[u].s[0]].size+1,u=tr[u].s[1];//跳少了,到右子树
	}
	return -1;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<=n+1;i++) insert(i);//为什么0~n+1呢?因为有哨兵
	while(m--){
		int l,r;
		scanf("%d%d",&l,&r);
		l=get_k(l),r=get_k(r+2);//(l-1)+2,(r+1)+1
		splay(l,0),splay(r,l);//把lsplay到根,在把rsplay到l下面
		tr[tr[r].s[0]].flag^=1;
	}
	output(root);
	puts("");
	system("pause");
	return 0;
}

后缀数组(SA)

/*************************************************************************
    > File Name: p3809[模板]后缀排序.cpp
    > Author: typedef
    > Mail: 1815979752@qq.com 
    > Created Time: 2021/2/23 7:43:45
 ************************************************************************/
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+7;
int n,m;
char s[N];
int sa[N],x[N],y[N],c[N],rk[N],height[N];//x是第一关键字,y是第二关键字,c是关键字的个数
void get_sa(){
	for(int i=1;i<=n;i++) c[x[i]=s[i]]++;
	for(int i=2;i<=m;i++) c[i]+=c[i-1];
	for(int i=n;i;i--) sa[c[x[i]]--]=i;
	for(int k=1;k<=n;k<<=1){
		int num=0;
		for(int i=n-k+1;i<=n;i++) y[++num]=i;
		for(int i=1;i<=n;i++)
			if(sa[i]>k) y[++num]=sa[i]-k;
		for(int i=1;i<=m;i++) c[i]=0;
		for(int i=1;i<=n;i++) c[x[i]]++;
		for(int i=2;i<=m;i++) c[i]+=c[i-1];
		for(int i=n;i;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;
		swap(x,y);
		x[sa[1]]=1,num=1;
		for(int i=2;i<=n;i++)
			x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
		if(num==n) break;
		m=num;
	}
	return;
}
void get_height(){
	for(int i=1;i<=n;i++) rk[sa[i]]=i;
	for(int i=1,k=0;i<=n;i++){
		if(rk[i]==1) continue;
		if(k) k--;
		int j=sa[rk[i]-1];
		while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
		height[rk[i]]=k;
	}
}
int main(){
	scanf("%s",s+1);
	n=strlen(s+1),m=122;
	get_sa();
//	get_height();
	for(int i=1;i<=n;i++) printf("%d ",sa[i]);
	puts("");
//	for(int i=1;i<=n;i++) printf("%d ",height[i]);
//	puts("");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值