Kruskal重构树+AC自动机+树状数组:Gym - 104542F

news/2025/1/15 23:48:53/

https://vjudge.net/contest/579844#problem/F

  1. 看到连边和没有强制在线,考虑Kruskal重构树
  2. 看到判断子串,考虑AC自动机+线段树

然后要非常大胆地把两个结合起来。

然后就是大码量了。

具体总结一下流程:

  1. 先建出Kruskal重构树
  2. 对Kruskal重构树处理出dfn序
  3. 重新对字符串进行排序
  4. 对字符串建AC自动机
  5. 对fail树处理出dfn序
  6. 对询问操作处理出Kruskal重构树上对应区间进行差分
  7. 按顺序加入每个字符串,在树状数组上进行区间加操作,树状数组维护差分
  8. 对于每个询问在Trie树上跑,在对应树状数组上询问并统计答案
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||
ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define N 500010
struct node {int id, f; 
};
int n, m, i, j, k, T;
int a[N], a_st[N], a_ed[N], num, tot; 
int dfn[N], ed[N], p[N], qqq, f[N], op, dian[N]; 
int ans[N]; 
int u, v; 
vector<int>G[N]; 
vector<node>Q[N]; 
vector<int>s[N], t[N], S[N]; 
char str[N]; 
queue<int>q; int fa(int x) {if(f[x]==x) return x; return f[x]=fa(f[x]); 
}void dfs(int x) {if(x<=n) a[++num]=x, a_st[x]=num; for(int y :  G[x]) {dfs(y); if(!a_st[x]) a_st[x]=a_st[y]; }a_ed[x]=num; 
}struct Tree_zhuang_number_group {int n, cnt[N]; void add(int x, int y) {while(x<=n)	 {cnt[x]+=y; x+=x&-x; }}int que(int x) {int ans=0; while(x) ans+=cnt[x], x-=x&-x; return ans; }
}Bin;struct AC_auto_machine {int tot=1, nxt[N][26], fail[N]; int dfn[N], ed[N], num; vector<int>G[N]; int Trie(int u, int i, int id) {if(!s[id][i]) return u; int c=s[id][i]-'a'; if(!nxt[u][c]) nxt[u][c]=++tot; return Trie(nxt[u][c], i+1, id); }void bfs() {q.push(1); while(!q.empty()) {u=q.front(); q.pop(); for(int i=0; i<26; ++i) {if(!nxt[u][i]) continue; v=nxt[u][i]; k=fail[u]; while(k && !nxt[k][i]) k=fail[k]; if(nxt[k][i]) fail[v]=nxt[k][i]; else fail[v]=1; q.push(v); }}}void pre_dfs() {for(int i=2; i<=tot; ++i) G[fail[i]].pb(i); }void dfs(int x) {dfn[x]=++num;for(int y : G[x]) dfs(y); ed[x]=num; }void jia(int i) {Bin.add(ed[p[i]]+1, -1); Bin.add(dfn[p[i]], 1); }int que(int id) {char c; int ans=0; for(int j=1, i=0; t[id][i]; ++i) {c=t[id][i]-'a'; while(j && !nxt[j][c]) j=fail[j]; if(nxt[j][c]) j=nxt[j][c]; else j=1; ans+=Bin.que(dfn[j]); }return ans; }
}AC;signed main()
{
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);n=read(); for(i=1; i<=n; ++i) {scanf("%s", str+1); for(j=1; str[j]; ++j) S[i].pb(str[j]); S[i].pb(0); }qqq=read(); tot=n; for(i=1; i<=2*n; ++i) f[i]=i; while(qqq--) {op=read(); if(op==1) {u=read(); v=read(); u=fa(u); v=fa(v); if(u==v) continue; ++tot; G[tot].pb(u); G[tot].pb(v); f[u]=tot; f[v]=tot; }else {u=read(); scanf("%s", str+1); u=fa(u); ++m; dian[m]=u; for(j=1; str[j]; ++j) t[m].pb(str[j]); t[m].pb(0); }} for(i=1; i<=tot; ++i) if(fa(i)==i) G[tot+1].pb(i), f[i]=tot+1; ++tot; dfs(tot); for(i=1; i<=n; ++i) s[i]=S[a[i]]; for(i=1; i<=n; ++i) {p[i]=AC.Trie(1, 0, i); }AC.bfs(); AC.pre_dfs(); 	AC.dfs(1); Bin.n=AC.tot; for(i=1; i<=m; ++i) {Q[a_st[dian[i]]-1].pb({i, -1}); Q[a_ed[dian[i]]].pb({i, 1}); }for(i=1; i<=n; ++i) {AC.jia(i);for(node x : Q[i]) {ans[x.id]+=x.f*AC.que(x.id); }}for(i=1; i<=m; ++i) printf("%lld\n", ans[i]); return 0;
}``

http://www.ppmy.cn/news/1115563.html

相关文章

vue3+ts 实现移动端分页

current 开始页码 pageSize 结束页码 const sizeref<number>(10) //一页显示十条 const eachCurrentPageref<number>(1) //默认是第一页interface ITdata {current: number,pageSize: number,// xxxx 其他参数... } const selectApplyList ref<…

九芯电子丨语音智能风扇,助您畅享智慧生活

回忆童年时期的传统机械风扇&#xff0c;那“古老”的扇叶连摆动看起来是那么吃力。在一个闷热的夏夜&#xff0c;风扇的噪音往往令人印象深刻。但在今天&#xff0c;静音家用风扇已取代了传统的机械风扇。与此同时&#xff0c;随着智能化的发展&#xff0c;智能家居已逐渐成为…

Xcode14.3.1 真机调试iOS17的方法(无iOS17 DeviceSupport)

由于iOS17需要使用Xcode15 才能调试&#xff0c;而当前Xcode15都是beta&#xff0c;正式版还未出&#xff0c;那么要真机调试iOS17的方式一般有两种&#xff1a; 方法一&#xff1a; 一种是下载新的Xcode15 beta版 &#xff08;但Xcode包一般比较大&#xff0c;好几个G&#…

关于第一届全球电子纸创新应用金奖征集评选及报名指南

重要通知 &#xff5c;关于第一届全球电子纸创新应用金奖征集评选及报名指南https://mp.weixin.qq.com/s/RWsZtmJ20-NZXMG0k0rwPA?wxwork_useridEPIA 从2004年&#xff0c;Sony推出全球首款电纸书阅读器至今20载&#xff0c;这期间&#xff0c;到底诞生了多少种创新产品&#…

微信小程序传参的五种方式

文章目录 前言一、URL参数传递1.api跳转2.组件跳转 二、Storage本地存储三、全局变量globalData四、页面跳转时传参五、页面栈传参总结结语 前言 大家好&#xff0c;今天和大家分享一下微信小程序页面之间传参的五种方式&#xff0c;这个的话也是有人问了我一嘴&#xff0c;然…

【送书活动1】强势挑战Java,Kotlin杀回TIOBE榜单Top 20!

⭐简单说两句⭐ 作者&#xff1a;后端小知识 CSDN个人主页&#xff1a;后端小知识 &#x1f50e;GZH&#xff1a;后端小知识 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 强势挑战Java&#xff0c;Kotlin杀回TIOBE榜单Top 20&#xff01; …

C#webform Static DataTable 多人同时操作网页数据重复问题

在C# Web Forms中&#xff0c;如果声明一个static变量&#xff0c;它将在整个应用程序域&#xff08;Application Domain&#xff09;中保持持久化状态。每个用户的请求都在同一个应用程序域中处理&#xff0c;因此static变量在不同页面间保持相同的值。 当一个用户发起请求时…

python抠图(去水印)开源库lama-cleaner入门应用实践

1. 关于 Lama Cleaner Lama Cleaner 是由 SOTA AI 模型提供支持的免费开源图像修复工具。可以从图片中移除任何不需要的物体、缺陷和人&#xff0c;或者擦除并替换&#xff08;powered by stable diffusion&#xff09;图片上的任何东西。 特征&#xff1a; 完全免费开源&am…