[gym104542F] Interesting String Problem
Since you are a good friend of Jaber and Eyad, they are asking for your help to solve this problem.
You are given a graph consisting of \(n\) nodes, which initially has no edges. For each node \(i\),there's a string \(s_i\)
of lowercase Latin letters written on it.
You have to process \(q\) queries of two types:
- 1 \(u\) \(v\) : it means add an edge between node uand node v.
- 2 \(u\) \(t\) : it means for node \(u\) and string \(t\), output the sum of \(cnt_v\) over all nodes \(v\) which belong to the same component as \(u\),where \(cnt_v\) is the number of times \(s_v\) occurs in \(t\) as a substring.
It is guaranteed that the sum of lengths of sv doesn't exceed \(5\times10^5\), and sum of lengths of the query strings doesn't exceed \(5\times10^5\)
1 二进制分组
合并的时候,AC 自动机很难合并,所以考虑定期重构。
对每个点开一个栈,分别表示 \(2^i\) 个串的合并。加入栈时,如果同时存在两个有 \(2^i\) 个串的时候就把他重构成一个 \(2^{i+1}\) 的串。观察到每个串都会被重构 \(\log n\) 次,算上重构,复杂度就 \(O(|S_i|log n|\Sigma|)\)
2.线段树合并。
由于一开始就把所有的串给了出来,所以可以直接给他跑一个 AC 自动机,弄出fail 树。
考虑我后面的询问需要知道什么,需要知道这个点在 fail 树上有多少个祖先是和 \(x\) 在同一个连通块里面的。所以可以用线段树合并去维护这个东西。在第 \(x\) 棵线段树上把 \(dfn_x,dfn_x+sz_x-1\) 这段区间赋值成 \(1\),然后进行线段树合并,单点查询就可以得到答案了。
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,M=2e5+5;;
int idx,tr[N][26],tme=-1,hd[N],dfn[N],sz[N],u,v,fa[N],op,n,fil[N],q[N],l,r,e_num;
long long ans;
char str[N];
struct edge{
int v,nxt;
}e[N<<1];
string s[M];
void add_edge(int u,int v)
{
e[++e_num]=(edge){v,hd[u]};
hd[u]=e_num;
}
int read()
{
int s=0;
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
while(ch>='0'&&ch<='9')
s=s*10+ch-48,ch=getchar();
return s;
}
struct segment{
int rt[M],tr[N*30],lc[N*30],rc[N*30],idx;
int merge(int u,int v)
{
if(!u||!v)
return u|v;
tr[u]+=tr[v];
lc[u]=merge(lc[u],lc[v]);
rc[u]=merge(rc[u],rc[v]);
return u;
}
void upd(int&o,int l,int r,int x,int y)
{
if(!o)
o=++idx;
if(x<=l&&r<=y)
{
tr[o]++;
return;
}
int md=l+r>>1;
if(md>=x)
upd(lc[o],l,md,x,y);
if(md<y)
upd(rc[o],md+1,r,x,y);
}
int qry(int&o,int l,int r,int x)
{
if(!o)
return 0;
if(l==r)
return tr[o];
int md=l+r>>1;
if(md>=x)
return qry(lc[o],l,md,x)+tr[o];
return qry(rc[o],md+1,r,x)+tr[o];
}
void mge(int x,int y)
{
rt[y]=merge(rt[y],rt[x]);
}
}b;
void insert(string s,int x)
{
int u=0;
for(int i=0;i<s.size();i++)
{
if(!tr[u][s[i]-'a'])
tr[u][s[i]-'a']=++idx;
u=tr[u][s[i]-'a'];
}
}
void build()
{
l=1,r=0;
for(int i=0;i<26;i++)
if(tr[0][i])
q[++r]=tr[0][i];
while(l<=r)
{
for(int i=0;i<26;i++)
{
if(tr[q[l]][i])
fil[q[++r]=tr[q[l]][i]]=tr[fil[q[l]]][i];
else
tr[q[l]][i]=tr[fil[q[l]]][i];
}
++l;
}
for(int i=1;i<=idx;i++)
add_edge(fil[i],i);
}
void sou(int x)
{
dfn[x]=++tme,sz[x]=1;
for(int i=hd[x];i;i=e[i].nxt)
sou(e[i].v),sz[x]+=sz[e[i].v];
}
int find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
scanf("%s",str),insert(s[i]=str,fa[i]=i);
build();
sou(0);
for(int i=1;i<=n;i++)
{
int u=0;
for(int j=0;j<s[i].size();j++)
u=tr[u][s[i][j]-'a'];
b.upd(b.rt[i],0,idx,dfn[u],dfn[u]+sz[u]-1);
}
int q=read();
while(q--)
{
op=read();
if(op==1)
{
u=read(),v=read();
if(find(u)^find(v))
{
b.mge(find(u),find(v));
fa[find(u)]=find(v);
}
}
else
{
ans=0;
u=read(),scanf("%s",str);
u=find(u);
int k=0;
for(int i=0;str[i];i++)
{
k=tr[k][str[i]-'a'];
ans+=b.qry(b.rt[u],0,idx,dfn[k]);
}
printf("%lld\n",ans);
}
}
}
- Kruskal重构树。
给询问他建一个 kruskal 重构树,然后一次询问在 kruskal 重构树上是一段连续区间 \([l,r]\) 的询问,可以拆成 \(l-1\) 和 \(r\) 的询问,不断给线段树中加入元素,回答询问即可。
[gym104542F] Interesting String Problem的更多相关文章
- FZU - 2218 Simple String Problem(状压dp)
Simple String Problem Recently, you have found your interest in string theory. Here is an interestin ...
- hdu String Problem(最小表示法入门题)
hdu 3374 String Problem 最小表示法 view code#include <iostream> #include <cstdio> #include &l ...
- HDU 3374 String Problem(KMP+最大/最小表示)
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 【HDU3374】 String Problem (最小最大表示法+KMP)
String Problem Description Give you a string with length N, you can generate N strings by left shift ...
- HDOJ3374 String Problem 【KMP】+【最小表示法】
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- HDU 3374 String Problem (KMP+最大最小表示)
HDU 3374 String Problem (KMP+最大最小表示) String Problem Time Limit: 2000/1000 MS (Java/Others) Memory ...
- String Problem hdu 3374 最小表示法加KMP的next数组
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- ACM-ICPC2018南京赛区 Mediocre String Problem
Mediocre String Problem 题解: 很容易想到将第一个串反过来,然后对于s串的每个位置可以求出t的前缀和它匹配了多少个(EXKMP 或者 二分+hash). 然后剩下的就是要处理以 ...
- hdu3374 String Problem【最小表示法】【exKMP】
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu 5772 String problem 最大权闭合子图
String problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5772 Description This is a simple pro ...
随机推荐
- Linux校验文件MD5和SHA值的方法
1.需求背景 下载或传输文件后,需要计算文件的MD5.SHA256等校验值,以确保下载或传输后的文件和源文件一致 2.校验方法 如上图所示,可以使用Linux自带的校验命令来计算一个文件的校验值 Li ...
- B3612 【深进1.例1】求区间和(前缀和)
[深进1.例1]求区间和 [深进1.例1]求区间和 题目描述 给定 \(n\) 个正整数组成的数列 \(a_1, a_2, \cdots, a_n\) 和 \(m\) 个区间 \([l_i,r_i]\ ...
- 论文解读(AdSPT)《Adversarial Soft Prompt Tuning for Cross-Domain Sentiment Analysis》
Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:Adversarial Soft Prompt Tuning for Cross-Domain Senti ...
- 2017-D
2017-D 数据库部分 使用Windows 身份验证登录SQL Server ,建立数据库test0322,文件日志保存到一个专门的文件夹 建表 备份数据库,选定所创建数据库,右键-任务-备份-选择 ...
- selenium库浅析
selenium库浅析 基于4.3 pip install selenium安装好后,在sitepackages下 2个主要的目录,common和webdriver 1- common 该目录一共就一 ...
- 解决Dependency 'fastdfs-client-java’not found
如何能把 fastdfs的jar包安装到本地的仓库中(因为中央仓库没有FASTDFS的jar包地址) 1.首先去github上下载下来fastdfs的压缩包 下载链接 然后直接解压出来 2.使用cmd ...
- CF862B
题目简化和分析: 这是一道较为经典的二分图染色题. 二分图的基本概念 但这题让我们求得是完全二分图. 什么是完全二分图 \(cnt_{1}\) 表示染成颜色种类为 \(1\) 的个数. \(cnt_{ ...
- Zuul 2.1.5 设计分析
前言 https://github.com/Netflix/zuul zuul 是 SpringCloud 家族老兵,使用 Java 微服务大部分都在使用 zuul 作为网关.既然他如此重要,那么我们 ...
- 文心一言 VS 讯飞星火 VS chatgpt (117)-- 算法导论10.3 2题
二.用go语言,对一组同构对象用单数组表示法实现,写出过程ALLOCATE-OBJECT和FREE-OBJECT. 文心一言: 在Go语言中,我们通常使用指针和结构体来表示和操作复杂的数据结构.对于一 ...
- sql优化的方法总结
1.对查询进行优化,应该尽量避免全表扫描,首先应考虑在where和order by涉及的列上建立索引 2.应尽量避免在where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表 ...