【HDU5566】Clarke and room(AC自动机)(树链剖分)(线段树)

匿名 (未验证) 提交于 2019-12-03 00:11:01

传送门


题解:

在线也好离线也好,反正AC自动机只建在有询问的线段树节点上就行了。

由于树链剖分形态的特殊性,可能很多线段树节点上都没有询问(是两条链标号的并),建出来就是浪费时间。


代码:

#include<bits/stdc++.h> #define ll long long #define re register #define gc get_char  #define cs const  namespace IO{ 	inline char get_char(){ 		static cs int Rlen=1<<22|1; 		static char buf[Rlen],*p1,*p2; 		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++; 	} 	 	inline int get_s(char *s){ 		int len=0;char c; 		while(isspace(c=gc())); 		while(s[len++]=c,!isspace(c=gc())&&c!=EOF); 		s[len]='\0';return len; 	} 	 	template<typename T> 	inline T get(){ 		char c;T num; 		while(!isdigit(c=gc()));num=c^48; 		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48); 		return num; 	} 	inline int gi(){return get<int>();} } using namespace IO;  using std::cerr; using std::cout;  cs int N=1e5+7;  using std::string;  inline string get_s(){ 	static char s[N]; 	int len=get_s(s); 	return string(s,s+len); }  namespace AC{ 	int son[N][26],fail[N],d[N],ed[N],tot; 	inline void clear(){ 		memset(son,0,sizeof(int)*(tot+1)*26); 		memset(fail,0,sizeof(int)*(tot+1)); 		memset(d,0,sizeof(int)*(tot+1)); 		memset(ed,0,sizeof(int)*(tot+1)); 		tot=0; 	} 	 	inline void ins(cs string &s){ 		int len=s.size(),u=0; 		for(int re i=0;i<len;++i){ 			int c=s[i]-'a'; 			if(!son[u][c]){ 				son[u][c]=++tot; 				d[tot]=d[u]+1; 			} 			u=son[u][c]; 		}ed[u]=d[u]; 	} 	 	inline void build(){ 		std::queue<int> q; 		for(int re i=0;i<26;++i)if(son[0][i])q.push(son[0][i]); 		while(!q.empty()){ 			int u=q.front();q.pop();ed[u]=std::max(ed[u],ed[fail[u]]); 			for(int re i=0;i<26;++i) 			son[u][i]?(q.push(son[u][i]),fail[son[u][i]]=son[fail[u]][i]):(son[u][i]=son[fail[u]][i]); 		} 	} 	 	inline int match(cs string &s){ 		int len=s.size(),u=0,ans=0; 		for(int re i=0;i<len;++i){ 			int c=s[i]-'a'; 			u=son[u][c]; 			ans=std::max(ans,ed[u]); 		} 		return ans; 	} }  int n,m;  int el[N],nxt[N]; inline void adde(int u,int v){nxt[v]=el[u],el[u]=v;}  int fa[N],son[N],d[N],siz[N],top[N],in[N],nd[N],dfn;  void dfs1(int u,int p){ 	siz[u]=1;son[u]=0;d[u]=d[p]+1; 	for(int re v=el[u];v;v=nxt[v]){ 		dfs1(v,u);siz[u]+=siz[v]; 		if(siz[v]>siz[son[u]])son[u]=v; 	} }  void dfs2(int u,int tp){ 	nd[in[u]=++dfn]=u;top[u]=tp; 	if(son[u])dfs2(son[u],tp); 	for(int re v=el[u];v;v=nxt[v])if(v!=son[u])dfs2(v,v); }  string name[N],s[N]; int ans[N];  inline void work(int l,int r,cs std::vector<int> &q){ 	if(!q.size())return ; 	AC::clear(); 	for(int re i=l;i<=r;++i)AC::ins(name[nd[i]]);AC::build(); 	for(int re i:q)ans[i]=std::max(ans[i],AC::match(s[i])); }  namespace SGT{ #define lc ((u)<<1) #define rc (lc|1) 	cs int N=::N<<2; 	std::vector<int> q[N]; 	inline void build(int u,int l,int r){ 		q[u].clear();if(l==r)return ; 		int mid=l+r>>1; 		build(lc,l,mid);build(rc,mid+1,r); 	} 	 	inline void ins(int u,int l,int r,int ql,int qr,int id){ 		if(ql<=l&&r<=qr){q[u].push_back(id);return ;} 		int mid=l+r>>1; 		if(ql<=mid)ins(lc,l,mid,ql,qr,id); 		if(mid<qr)ins(rc,mid+1,r,ql,qr,id); 	} 	 	inline void seg_dfs(int u,int l,int r){ 		work(l,r,q[u])        
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!