ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF710F String Set Queries

2022-03-19 13:35:53  阅读:172  来源: 互联网

标签:AC Set 20 String int long log Queries define


题面传送门
完全颠覆了我对于二进制分组的认知,本来以为那东西只能优化多重背包还被单调队列吊起来打来着。
首先这个题如果不强制在线可以发现就是个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);}
	}
}

标签:AC,Set,20,String,int,long,log,Queries,define
来源: https://www.cnblogs.com/275307894a/p/16026112.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有