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);
}
}
}
  1. Kruskal重构树。

给询问他建一个 kruskal 重构树,然后一次询问在 kruskal 重构树上是一段连续区间 \([l,r]\) 的询问,可以拆成 \(l-1\) 和 \(r\) 的询问,不断给线段树中加入元素,回答询问即可。

[gym104542F] Interesting String Problem的更多相关文章

  1. FZU - 2218 Simple String Problem(状压dp)

    Simple String Problem Recently, you have found your interest in string theory. Here is an interestin ...

  2. hdu String Problem(最小表示法入门题)

    hdu 3374 String Problem 最小表示法 view code#include <iostream> #include <cstdio> #include &l ...

  3. HDU 3374 String Problem(KMP+最大/最小表示)

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  4. 【HDU3374】 String Problem (最小最大表示法+KMP)

    String Problem Description Give you a string with length N, you can generate N strings by left shift ...

  5. HDOJ3374 String Problem 【KMP】+【最小表示法】

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  6. HDU 3374 String Problem (KMP+最大最小表示)

    HDU 3374 String Problem (KMP+最大最小表示) String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory ...

  7. String Problem hdu 3374 最小表示法加KMP的next数组

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  8. ACM-ICPC2018南京赛区 Mediocre String Problem

    Mediocre String Problem 题解: 很容易想到将第一个串反过来,然后对于s串的每个位置可以求出t的前缀和它匹配了多少个(EXKMP 或者 二分+hash). 然后剩下的就是要处理以 ...

  9. hdu3374 String Problem【最小表示法】【exKMP】

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  10. hdu 5772 String problem 最大权闭合子图

    String problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5772 Description This is a simple pro ...

随机推荐

  1. 【opencv】传统目标检测:Haar检测器实现人脸检测

    传统目标分类器主要包括Viola Jones Detector.HOG Detector.DPM Detector,本文主要介绍VJ检测器,在VJ检测器基础上发展出了Haar检测器,Haar检测器也是 ...

  2. from itertools import groupby

    需求:期望由 a 得到 b 实现方法: from itertools import groupby a = [ {'name': 'a', 'value': 1}, {'name': 'b', 'va ...

  3. Spring Boot 中使用 Poi-tl 渲染数据并生成 Word 文档

    本文 Demo 已收录到 demo-for-all-in-java 项目中,欢迎大家 star 支持!后续将持续更新! 前言 产品经理急冲冲地走了过来.「现在需要将按这些数据生成一个 Word 报告文 ...

  4. 如何保持 SSH 会话不中断?

    哈喽大家好,我是咸鱼 不知道小伙伴们有没有遇到过下面的情况: 使用终端(XShell.secureCRT 或 MobaXterm 等)登录 Linux 服务器之后如果有一段时间没有进行交互,SSH 会 ...

  5. HTML网页/KRPano项目一键打包EXE工具(HTML网页打包成单个windows可执行文件exe)

    HTML一键打包EXE工具使用说明 工具简介 HTML一键打包EXE工具(HTML封装EXE,桌件)能把任意HTML项目(网址)一键打包为单个EXE文件,可以脱离浏览器和服务器,直接双击即可运行.支持 ...

  6. python入门基础(14)--类的属性、成员方法、静态方法以及继承、重载

    上一篇提到过类的属性,但没有详细介绍,本篇详细介绍一下类的属性 一 .类的属性 方法是用来操作数据的,而属性则是建模必不的内容,而且操作的数据,大多数是属性,比如游戏中的某个boss类,它的生命值就是 ...

  7. Solution Set -「ARC 124」

    「ARC 124A」LR Constraints Link. 我们可以把 \(1\sim n\) 个盒子里能放的球的编号集合全部求出来.然后就直接来. 注意题目已经给出了 \(k\) 个球的位置,所以 ...

  8. 在 Net7.0 环境下使用 RestSharp 发送 Http(FromBody和FromForm)请求

    一.简介 最近,在做一个数据传输的服务,我在一个Worker Service里面需要访问 WebAPI 接口,并传输数据,也可以提交数据.由于第一次使用 RestSharp 发送请求,也遇到了很多问题 ...

  9. 485modbus转profinet网关连接威纶通与三菱变频器modbus通讯

    485modbus转profinet网关连三菱变频器modbus通讯触摸屏监控 本案例介绍了如何通过485modbus转profinet网关连接威纶通与三菱变频器进行modbus通讯.485modbu ...

  10. C++ STL 容器简单讲解

    STL 简单讲解 网上有很多很好的资料可以参考 而直接看标准是最准确清晰的 vector stack queue / priority_queue deque array map / multimap ...