传送门
题解:
在线也好离线也好,反正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])