题目

【题目描述】

Yazid 和 Tiffany 喜欢字符串问题。在这里,我们将给你介绍一些关于字符串的基本概念。

对于一个字符串 $S$, 我们定义 $\lvert S\rvert$ 表示 $S$ 的长度。

接着,我们定义该串的子串 $S\left( {L,R}\right)$ 表示由 $S$ 中从左往右数,第 $L$ 个字符到第 $R$ 个字符依次连接形成的字符串,特别地,如果 $L < 1$ 或 $R > \lvert S\rvert$ 或 $L > R$,则 $S\left( {L,R}\right)$ 表示空串。

我们说两个字符串相等,当且仅当它们的长度相等,且从左至右各位上的字符依次相同。

我们说一个字符串 $T$ 是 $S$ 的**前缀**,当且仅当 $S\left( 1,\lvert T\rvert\right)=T$。

两个字符串 $S,T$ 相加 $S+T$ 表示的是在 $S$ 后紧挨着写下 $T$ 得到的长度为 $\lvert S\rvert+\lvert T\rvert$ 的字符串。

#### 题目描述
现有一个字符串 $S$。

Tiffany 将从中划出 $n_a$ 个子串作为 A 类串,第 $i$ 个($1\leq i\leq n_a$)为 $A_i = S\left( la_i, ra_i\right)$。

类似地,Yazid 将划出 $n_b$ 个子串作为 B 类串,第 $i$ 个($1\leq i\leq n_b$)为 $B_i = S\left( lb_i, rb_i\right)$。

现额外给定 $m$ 组支配关系,每组支配关系 $\left( x,y\right)$ 描述了第 $x$ 个 A 类串**支配**第 $y$ 个 B 类串。

求一个**长度最大**的目标串 $T$,使得存在一个串 $T$ 的分割 $T=t_1 + t_2 +\dots +t_k$($k\geq 0$)满足:

- 分割中的每个串 $t_i$ 均为 A 类串:即存在一个与其相等的 A 类串,不妨假设其为 $t_i = A_{id_i}$。
- 对于分割中所有相邻的串 $t_i , t_{i+1}$($1\leq i < k$),都有存在一个 $A_{id_i}$ 支配的 B 类串,使得该 B 类串为 $t_{i+1}$ 的前缀。

方便起见,你只需要输出这个最大的长度即可。

特别地,如果存在无限长的目标串(即对于任意一个正整数 $n$,都存在一个满足限制的长度超过 $n$ 的串),请输出 $-1$。

【输入格式】

从标准输入读入数据。

单个测试点中包含多组数据,输入的第一行包含一个非负整数 $T$ 表示数据组数。接下来依次描述每组数据,对于每组数据:

- 第 $1$ 行一个只包含小写字母的字符串 $S$。
- 第 $2$ 行一个非负整数 $n_a$,表示 A 类串的数目。接下来 $n_a$ 行,每行 $2$ 个用空格隔开的整数。
- 这部分中第 $i$ 行的两个数分别为 $la_i,ra_i$,描述第 $i$ 个 A 类串。
- 保证 $1\leq la_i\leq ra_i\leq \lvert S\rvert$。
- 接下来一行一个非负整数 $n_b$,表示 B 类串的数目。接下来 $n_b$ 行,每行 $2$ 个用空格隔开的整数。
- 这部分中第 $i$ 行的两个数分别为 $lb_i,rb_i$,描述第 $i$ 个 B 类串。
- 保证 $1\leq lb_i\leq rb_i\leq \lvert S\rvert$。
- 接下来一行一个非负整数 $m$,表示支配关系的组数。接下来 $m$ 行,每行 $2$ 个用空格隔开的整数。
- 这部分中每行的两个整数 $x,y$,描述一对 $\left( x,y\right)$ 的支配关系,具体意义见「题目描述」。
- 保证 $1\leq x\leq n_a$,$1\leq y\leq n_b$。保证所有支配关系两两不同,即不存在两组支配关系的 $x,y$ **均**相同。

【输出格式】

输出到标准输出。

依次输出每组数据的答案,对于每组数据,一行一个整数表示最大串长。特别地,如果满足限制的串可以是无限长的,则请输出 $-1$。

【样例输入】

3
abaaaba
2
4 7
1 3
1
3 4
1
2 1
abaaaba
2
4 7
1 3
1
7 7
1
2 1
abbaabbaab
4
1 5
4 7
6 9
8 10
3
1 6
10 10
4 6
5
1 2
1 3
2 1
3 3
4 1

【样例输出】

7
-1
13

【样例解释】

对于第 $1$ 组数据,A 类串有 `aaba` 与 `aba`,B 类串有 `aa`,且 $A_2$ 支配 $B_1$。我们可以找到串 `abaaaba`,它可以拆分成 $A_2 + A_1$,且 $A_1$ 包含由 $A_2$ 所支配的 $B_1$ 作为前缀。可以证明不存在长度更大的满足限制的串。

对于第 $2$ 组数据,与第 $1$ 组数据唯一不同的是,唯一的 B 类串为 `a`。容易证明存在无限长的满足限制的串。

对于第 $3$ 组数据,容易证明 `abbaabbaaaabb` 是最长的满足限制的串。

【数据范围与提示】

|$n_a$|$n_b$|$\lvert S\rvert$|测试点|$m$|$\lvert A_i\rvert \geq \lvert B_j\rvert$|其他限制|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|$\leq 100$|$\leq 100$|$\leq 10^4$|$1$|$\leq 10^4$|保证|保证所有 $\lvert A_i\rvert,\lvert B_j\rvert\leq 100$|
|$\leq 1000$|$\leq 1000$|$\leq 2\times 10^5$|$2\sim 3$|$\leq 2\times 10^5$|保证|无|
|$=1$|$\leq 2\times 10^5$|$\leq 2\times 10^5$|$4$|$=n_b$|保证|无|
|$\leq 2\times 10^5$|$\leq 2\times 10^5$|$\leq 2\times 10^5$|$5\sim 6$|$\leq 2\times 10^5$|保证|保证所有 $ra_i +1=la_{i+1}$|
|$\leq 2\times 10^5$|$\leq 2\times 10^5$|$\leq 2\times 10^5$|$7\sim 8$|$\leq 2\times 10^5$|保证|无|
|$\leq 2\times 10^5$|$\leq 2\times 10^5$|$\leq 2\times 10^5$|$9\sim 10$|$\leq 2\times 10^5$|不保证|无|

为了方便你的阅读,我们把**测试点编号**放在了表格的中间,请你注意这一点。

表格中的 $\lvert A_i\rvert \ge \lvert B_j\rvert$ 指的是**任意** B 类串的长度不超过**任意** A 类串的长度。

对于所有测试点,保证:$T\leq 100$,且对于测试点内所有数据,$\lvert S\rvert,n_a,n_b,m$ 的**总和**分别不会超过**该测试点中对应**的**单组数据的限制**的 $10$ 倍。比如,对于第 1 组测试点,就有 $\sum n_a\leq 10\times 100=1000$ 等。特别地,我们规定对于测试点 4,有 $T\leq 10$。

对于所有测试点中的每一组数据,保证:$1\leq \lvert S\rvert\leq 2\times 10^5$,$n_a , n_b\leq 2\times 10^5$,$m\leq 2\times 10^5$。

#### 提示
十二省联考命题组温馨提醒您:

**数据千万条,清空第一条。**

**多测不清空,爆零两行泪。**

题解

首先想到的是暴力判断 $ b_j $ 是否为 $ a_i $ 前缀,效率为 $ O(n^2) $,卡一卡能过前 $ 40 \% $

考虑优化寻找过程,如果将串反过来,那么前缀就变成了后缀,那么就想到了后缀自动机

对于后缀自动机的每一个节点,都是其子树的前缀,那么直接按着 parent 树建图即可,可以过 $ 80 \% $

但上述做法是错的,因为 $ |a_i|>|b_j| $,所以当节点 $ x $ 有 $ |b_1|=5,|a_1|=6,|b_2|=7 $ 时,$ a_1 $ 会有一条连向 $ b_2 $ 的边,直接 GG

考虑修改建图的过程,将属于 $ x $ 的 $ a,b $ 排序,由 $ b $ 小的向大的连边,每一个 $ a $ 连向最大的比它小的 $ b $,这样子就可以避免以上的问题了,并且每一个 $ b $ 仅向他的儿子的 $ b $ 的结尾连边,这样子边数的复杂度为 $ O(n) $

然后在建出的图跑 DAG+DP,如果有环就是 -1,不然就是最长路

时间效率:$ O(nlogn) $,主要在建后缀自动机和求对应的节点上

然后在 $dis[v=e[k].to]=max(dis[v],dis[now]+len[now])$ 上调到自闭,因为评测环境里从后往前做

数据千万条,清空第一条。

多测不清空,爆零两行泪

代码

 #include<bits/stdc++.h>
#define LL long long
#define pb push_back
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
int R(){
int x;bool f=;char ch;_(!)if(ch=='-')f=;x=ch^;
_()x=(x<<)+(x<<)+(ch^);return f?x:-x;}
const int N=1e6+;
int n,m,lg,tot,ma,mb,head[N],dg[N],cnt,h[N],A[N],B[N];
struct edge{int to,nex;}e[N];
int las,Rt,tmp,fa[N][],tr[N][],len[N],id[N];
bool fl[N];LL dis[N];
char ch[N];
vector<int>g[N];queue<int> q;
void clean(){
tmp=;
memset(fa,,sizeof fa);
memset(tr,,sizeof tr);
memset(len,,sizeof len);
memset(fl,,sizeof fl);
memset(head,,sizeof head);
memset(dg,,sizeof dg);
memset(dis,,sizeof dis);
}
void add(int s,int t){
e[++cnt]=(edge){t,head[s]},head[s]=cnt,dg[t]++;}
void extend(int c){
int p=las,np=las=++tmp,q,nq;
len[np]=len[p]+;
while(!tr[p][c]&&p)tr[p][c]=np,p=fa[p][];
if(!p)return void(fa[np][]=Rt);
if(len[p]+==len[q=tr[p][c]])
return void(fa[np][]=q);
len[nq=++tmp]=len[p]+;
memcpy(tr[nq],tr[q],sizeof tr[q]);
fa[nq][]=fa[q][],fa[q][]=fa[np][]=nq;
while(p&&tr[p][c]==q)tr[p][c]=nq,p=fa[p][];
return;
}
void work(int k,int L,bool f){
for(int i=lg;~i;i--)
if(len[fa[k][i]]>=L)k=fa[k][i];
fl[++tot]=f,len[tot]=L,g[k].pb(tot);
}
bool cmp(int a,int b){return len[a]==len[b]?fl[a]>fl[b]:len[a]>len[b];}
LL topu(){
LL ans=;
for(int i=;i<=tot;i++){
if(!dg[i])q.push(i);
if(!fl[i])len[i]=;
}
while(!q.empty()){
int now=q.front();q.pop();
ans=max(ans,dis[now]+len[now]);
for(int k=head[now];k;k=e[k].nex){
int v=e[k].to;
dis[v]=max(dis[v],dis[now]+len[now]);
if(!(--dg[v]))q.push(v);
}
}
for(int i=;i<=tot;i++)if(dg[i])return -;
return ans;
}
int main(){
for(int T=R();T--;){
clean();
scanf("%s",ch+),n=strlen(ch+);
las=Rt=++tmp;
for(int i=n;i;i--)
extend(ch[i]-'a'),id[i]=las;
lg=log2(tmp)+;
for(int j=;j<=lg;j++)
for(int i=;i<=tmp;i++)
fa[i][j]=fa[fa[i][j-]][j-];
for(int i=;i<=tmp;i++)g[i].clear();
tot=tmp,ma=R();
for(int i=,l,r;i<=ma;i++)
l=R(),r=R(),work(id[l],r-l+,),A[i]=tot;
mb=R();
for(int i=,l,r;i<=mb;i++)
l=R(),r=R(),work(id[l],r-l+,),B[i]=tot;
cnt=;
for(int i=;i<=tmp;i++)sort(g[i].begin(),g[i].end(),cmp);
for(int i=;i<=tmp;i++){
int now=i;
for(int v,j=g[i].size()-;~j;j--){
add(now,v=g[i][j]);
if(!fl[v])now=v;
}
h[i]=now;
}
for(int i=;i<=tmp;i++)add(h[fa[i][]],i);
for(int x,y,i=m=R();i;i--)
x=R(),y=R(),add(A[x],B[y]);
printf("%lld\n",topu());
}
return ;
}

「十二省联考 2019」字符串问题——SAM+DAG的更多相关文章

  1. LOJ #3049. 「十二省联考 2019」字符串问题

    LOJ #3049. 「十二省联考 2019」字符串问题 https://loj.ac/problem/3049 题意:给你\(na\)个\(A\)类串,\(nb\)个\(B\)类串,\(m\)组支配 ...

  2. LOJ 3049: 洛谷 P5284: 「十二省联考 2019」字符串问题

    题目传送门:LOJ #3049. 题意简述: 给定一个长度为 \(n\) 的母串 \(S\). 有 \(n_a\) 个 A 类串,都是 \(S\) 的子串,以区间的形式给出. 有 \(n_b\) 个 ...

  3. 【LOJ 3049】「十二省联考 2019」字符串问题

    这个D1T2绝对有毒... 首先我们构造一把反串的后缀自动机. 然后我们就需要找到每一个子串在SAM上的节点. 这个可以通过扫描线+树上倍增处理. 首先我们把所有的子串按照左端点排序, 然后从右往左扫 ...

  4. 「ZJOI2019」&「十二省联考 2019」题解索引

    「ZJOI2019」&「十二省联考 2019」题解索引 「ZJOI2019」 「ZJOI2019」线段树 「ZJOI2019」Minimax 搜索 「十二省联考 2019」 「十二省联考 20 ...

  5. 【LOJ】#3051. 「十二省联考 2019」皮配

    LOJ#3051. 「十二省联考 2019」皮配 当时我在考场上觉得这题很不可做... 当然,出了考场后再做,我还是没发现学校和城市是可以分开的,导致我还是不会 事实上,若一个城市投靠了某个阵营,学校 ...

  6. 「十二省联考 2019」皮配——dp

    题目 [题目描述] #### 题目背景一年一度的综艺节目<中国好码农>又开始了.本季度,好码农由 Yazid.Zayid.小 R.大 R 四位梦想导师坐镇,他们都将组建自己的梦想战队,并率 ...

  7. 题解 loj3050 「十二省联考 2019」骗分过样例

    CASE \(1\sim 3\) \(n\)组测试数据,每次输入一个数\(x\),求\(19^x\). 测试点\(1\),\(x=0,1,\dots n-1\),可以直接递推. 测试点\(2\)要开l ...

  8. LOJ3048 「十二省联考 2019」异或粽子

    题意 题目描述 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 $n$ 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 $1$ 到 $n$.第 $i$ 种馅儿具 ...

  9. LOJ#3048. 「十二省联考 2019」异或粽子 Trie

    原文链接www.cnblogs.com/zhouzhendong/p/LOJ3048.html 题解 $O(n\log^2 {a_i})$ 的做法比较简单: 1. 求出第 k 大的是什么: 二分答案, ...

随机推荐

  1. LTE230方案示意图

    普天LTE230产品及解决方案   责任编辑:耿鹏飞 2016.12.26 16:42 来源:通信世界网 LTE230 普天   一.LTE230系统特点 (一)系统背景 随着社会的快速发展,能源危机 ...

  2. java代码排序问题

    总结: package com.ja; import java.util.Arrays; import java.util.Collections; public class mili { publi ...

  3. Mina APR传输与串口传输讲解---zhengli

    原文地址:Mina Transports(Apache Mina user guide Chapter6 Transport) 1.1.1.APR传输 1.1.1.1.介绍 APR (Apache P ...

  4. Oracle 下ASM磁盘总结

    Oracle 下ASM磁盘总结 文章转载: Oracle下创建ASM磁盘总结https://blog.csdn.net/okhymok/article/details/78791841?utm_sou ...

  5. 基于人脸识别+IMDB-WIFI+Caffe的性别识别

    本文用记录基于Caffe的人脸性别识别过程.基于imdb-wiki模型做finetune,imdb-wiki数据集合模型可从这里下载:https://data.vision.ee.ethz.ch/cv ...

  6. iOS中的数据存储

    SQLite3 SQLite3是一款开源的嵌入式关系型数据库,可移植性好,易使用,内存开销小. SQLite3是无类型的,意味着你可以保存任何类型的数据到任意表的任意字段中. SQLite3常用的4种 ...

  7. web基础 (二) html标签

    一.html是什么? 超文本标记语言(Hypertext Markup Language,HTML)通过标签语言来标记要显示的网页中的各个部分.一套规则,浏览器认识的规则 浏览器按顺序渲染网页文件,然 ...

  8. Python 学习之---文件目录处理

    前言:有关文件夹与文件的查找,删除等功能 在 os 模块中实现.使用时需先导入这个模块, 导入的方法是:import os   一.取得当前目录 s = os.getcwd() s 中保存的是当前目录 ...

  9. Runtime机制的使用整理

    一.基本概念 1.1.RunTime简称运行时,就是系统在运行的时候的一些机制,其中最主要的是消息机制. 1.2.对于C语言,函数的调用在编译的时候会决定调用哪个函数,编译完成之后直接顺序执行,无任何 ...

  10. 监控和安全运维 1.4 nagios安装

    1. Nagios 简介是一个开源软件,可以监控网络设备网络流量.Linux/windows主机状态,甚至可以监控打印机它可以运行在Linux上或windows上基于浏览器的web界面方便运维人员查看 ...