把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF710F String Set Queries

题面传送门
完全颠覆了我对于二进制分组的认知,本来以为那东西只能优化多重背包还被单调队列吊起来打来着。
首先这个题如果不强制在线可以发现就是个AC自动机sb题。
但是问题是它强制在线了,就有一些奇技淫巧来做。
首先显然可以对询问分块,但是有一个26的常数的根号显然跑不过去。
但是可以二进制分组呀。
就是像一个2048一样,每次在最后塞进去一个字符串然后长度相同不断合并,到最后只会剩下\(O(\log n)\)个AC自动机以及每个字符串最多会被合并\(O(\log n)\)次。
然后就做到了\(O(\sum{|T|}\log n)\)
合并啥的写个Trie合并就好了,虽然跑得有点慢。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N (300000+5)
#define M (400000+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,k,op,Hi,Hd,Io[20],Is[20],Do[20],Ds[20];char A[N];ll Ans;
namespace AC{
	int Len,Tp,x,FI[N],son[N][27],cnt,Val[N],F[N][27],S[N];queue<int> Q;I int Ins(char *s){x=Tp=++cnt;Len=strlen(s+1);for(RI i=1;i<=Len;i++) son[x][s[i]-'a']=++cnt,x=son[x][s[i]-'a'];Val[x]++;return Tp;}
	I void BFS(int x){RI i;S[x]=0;FI[x]=x;Mc(F[x],son[x]);for(i=0;i<26;i++) F[x][i]?(Q.push(F[x][i]),FI[F[x][i]]=x):(F[x][i]=x);
	while(!Q.empty()) for(x=Q.front(),Q.pop(),S[x]=S[FI[x]]+Val[x],Mc(F[x],son[x]),i=0;i<26;i++) F[x][i]?(Q.push(F[x][i]),FI[F[x][i]]=F[FI[x]][i]):(F[x][i]=F[FI[x]][i]);}
	I int ME(int x,int y){if(!x||!y) return x|y;Val[x]+=Val[y];for(RI i=0;i<26;i++) son[x][i]=ME(son[x][i],son[y][i]);return x;}
	I ll Qry(int x,char *A){ll Ans=0;Len=strlen(A+1);for(RI i=1;i<=Len;i++) x=F[x][A[i]-'a'],Ans+=S[x];return Ans;} 
}
int main(){
	freopen("1.in","r",stdin);
	RI i;scanf("%d",&n);while(n--){
		scanf("%d%s",&op,A+1);if(op==1){Io[++Hi]=AC::Ins(A);AC::BFS(Io[Hi]);Is[Hi]=1;while(Is[Hi]==Is[Hi-1]) Hi--,Is[Hi]<<=1,AC::ME(Io[Hi],Io[Hi+1]),AC::BFS(Io[Hi]);}
		else if(op==2){Do[++Hd]=AC::Ins(A);AC::BFS(Do[Hd]);Ds[Hd]=1;while(Ds[Hd]==Ds[Hd-1]) Hd--,Ds[Hd]<<=1,AC::ME(Do[Hd],Do[Hd+1]),AC::BFS(Do[Hd]);}
		else {Ans=0;for(i=1;i<=Hi;i++) Ans+=AC::Qry(Io[i],A);for(i=1;i<=Hd;i++) Ans-=AC::Qry(Do[i],A);printf("%lld\n",Ans);fflush(stdout);}
	}
}
posted @ 2022-03-19 13:14  275307894a  阅读(48)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end