CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心

Posted guangheli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心相关的知识,希望对你有一定的参考价值。

后缀自动机 + 线段树合并的裸题.

我这种大菜逼都秒切的题目,一定是送分题. 

#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin) 
#define maxn 220000   
using namespace std;
int n; 
int rt[maxn];   
namespace tr

	#define mid ((l+r)>>1)  
	#define lson t[x].l
	#define rson t[x].r 
	int cnt; 
	int newnode()  return ++cnt; 
	struct Node int l,r,sumv; t[maxn * 50]; 
	int merge(int u,int v)
	
		if(!u||!v) return u+v; 
		int x=newnode(); 
		t[x].sumv=t[u].sumv+t[v].sumv; 
		lson=merge(t[u].l,t[v].l); 
		rson=merge(t[u].r,t[v].r); 
		return x;             
	
	void update(int &x,int l,int r,int k,int delta)
	
		if(!x)x=newnode();                 
		t[x].sumv+=delta; 
		if(l==r) return; 
		if(k<=mid) update(lson, l, mid, k, delta); 
		else update(rson, mid + 1, r, k, delta);   
	 
	int query(int x,int l,int r,int L,int R)
	
		if(!x || L>R)return 0; 
		if(l>=L&&r<=R) return t[x].sumv; 
		int tmp=0; 
		if(L<=mid) tmp+=query(lson,l,mid,L,R); 
		if(R>mid) tmp+=query(rson, mid+1,r,L,R); 
		return tmp; 
	   
	#undef lson
	#undef rson  
; 
namespace SAM

	int tot,last; 
	int len[maxn], ch[maxn][30], f[maxn], rk[maxn], C[maxn]; 
	void init()  tot = last = 1;  
	void extend(int c)
	
		int np=++tot,p=last; 
		last=np, len[np]=len[p]+1; 
		while(p&&!ch[p][c]) ch[p][c]=np,p=f[p]; 
		if(!p) f[np]=1; 
		else 
		
			int q=ch[p][c]; 
			if(len[q]==len[p]+1) f[np]=q; 
			else 
			
				int nq=++tot; 
				len[nq]=len[p]+1; 
				memcpy(ch[nq],ch[q],sizeof(ch[q])); 
				f[nq]=f[q],f[np]=f[q]=nq;   
				while(p&&ch[p][c]==q) ch[p][c]=nq, p=f[p]; 
			
		
		tr::update(rt[np], 1, n, len[np], 1);   
	
	void prepare()
	
		int i,j; 
		for(i=1;i<=tot;++i) ++C[len[i]]; 
		for(i=1;i<=tot;++i) C[i]+=C[i-1]; 
		for(i=1;i<=tot;++i) rk[C[len[i]]--]=i;            
		for(i=tot;i>=1;--i)
		
			j=rk[i]; 
			rt[f[j]]=tr::merge(rt[f[j]], rt[j]); 
		    
	
; 
char str[maxn], T[maxn], stac[maxn]; 
int cur[maxn];         
int main()
 
	int i,j,Q; 
	// setIO("input"); 
	scanf("%s",str+1); 
	n=strlen(str+1);   
	SAM::init();      
	for(i=1;i<=n;++i)  
	
		SAM::extend(str[i]-‘a‘);  
	
	SAM::prepare();   
	scanf("%d",&Q);
	while(Q--)
	
		int l,r,_len,trace=0,top=0,L; 
		scanf("%d%d%s",&l,&r,T+1);    
		L=l;     
		_len=strlen(T+1);   
		cur[0]=1;   
		for(i=1;i<=min(_len,n-1);++i) 
		 
			int c=T[i]-‘a‘; 
			if(SAM::ch[cur[i-1]][c] && tr::query(rt[SAM::ch[cur[i-1]][c]], 1, n, l, r))     
			
				cur[i]=SAM::ch[cur[i-1]][c];
				++l,   trace=i, stac[++top]=T[i];         
			
			else break; 
		               
		T[0]=‘a‘;                                       
		int flag=0;
		for(i=min(n-1,trace);i>=0;--i)
		 
			int c= i + 1 > _len ? -1 : T[i+1] - ‘a‘;  
		//	if(flag) break;          
			for(j=c+1;j<27;++j) 
			
				if(SAM::ch[cur[i]][j] && tr::query(rt[SAM::ch[cur[i]][j]] , 1, n, l, r)) 
				           
					flag=1;          
					stac[++top]=‘a‘+j;   
					break; 
				
			
			if(flag) break; 
			--l; 
			--top;  
		     
		if(!flag) printf("-1\n"); 
		else 
		
			for(i=1;i<=top;++i) printf("%c",stac[i]); 
			printf("\n"); 
		
	
	return 0; 

  

以上是关于CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心的主要内容,如果未能解决你的问题,请参考以下文章

[CF1037H]Security

CF1037H Security 线段树合并 SAM

luoguCF1037H Security

CF235CCyclical Quest(后缀自动机)

CF873F Forbidden Indices [后缀自动机]

CF316G3Good Substrings 后缀自动机