[LOJ3049] [十二省联考 2019] 字符串问题
题目链接
LOJ:https://loj.ac/problem/3049
洛谷:https://www.luogu.org/problemnew/show/P5284
BZOJ:https://www.lydsy.com/JudgeOnline/problem.php?id=5496
Solution
小清新字符串题
不过小样例是真的强,窝调了一小时样例然后1A了
思路还是很清晰的,首先可以得到一个\(O(n^3)\)的暴力,我们直接大力枚举然后匹配连边,然后\(\rm toposort\)求最长连就好了,注意有环就无解。
然后我们大力优化这个暴力就好了,我们用后缀树优化建边,每个子串倍增定位,然后对应到后缀树的点上就好了。
但是这样是不对的,对于\(a\geqslant b\)的情况这样是没有问题的,否则一个点可能有很多\(a,b\),那么长度大的\(b\)不能连向\(a\)。
所以有两种思路,一是类似虚树的把所有需要用的点都建出来,二是每个点开个\(\rm vector\)然后把子串挂在\(\rm vector\)上,然后\(\rm sort\)之后连边就好了。
复杂度都是\(O(n\log n)\),下面代码写的是第二种。
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
#define ll long long
void print(ll x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define lf double
#define pii pair<int,int >
#define vec vector<int >
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
const int maxn = 8e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
ll dis[maxn];
char s[maxn];
vector<int > t[maxn];
int par[maxn],ml[maxn],tr[maxn][26],lstp=1,stot=1,fa[maxn][20];
int pos[maxn],na,nb,posa[maxn],posb[maxn],len[maxn],is[maxn],lst[maxn],d[maxn];
int head[maxn],tot;
struct edge{int to,nxt;}e[maxn<<1];
void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot,d[v]++;}
int append(int x) {
int p=lstp,np=++stot;lstp=np,ml[np]=ml[p]+1;
for(;p&&tr[p][x]==0;p=par[p]) tr[p][x]=np;
if(!p) return par[np]=1,np;
int q=tr[p][x];
if(ml[q]>ml[p]+1) {
int nq=++stot;ml[nq]=ml[p]+1;
memcpy(tr[nq],tr[q],sizeof tr[nq]);
par[nq]=par[q],par[q]=par[np]=nq;
for(;p&&tr[p][x]==q;p=par[p]) tr[p][x]=nq;
} else par[np]=q;
return np;
}
int cmp(int x,int y) {return len[x]==len[y]?is[x]<is[y]:len[x]<len[y];}
void build() {
scanf("%s",s+1);
for(int n=strlen(s+1),i=n;i;i--) pos[i]=append(s[i]-'a');
for(int i=2;i<=stot;i++) fa[i][0]=par[i];
for(int i=1;i<=18;i++)
for(int j=2;j<=stot;j++)
fa[j][i]=fa[fa[j][i-1]][i-1];
read(na);
for(int i=1;i<=na;i++) {
int l,r;read(l),read(r);
int now=pos[l];
for(int j=18;~j;j--) if(ml[fa[now][j]]>=r-l+1) now=fa[now][j];
t[now].push_back(posa[i]=++stot);
len[stot]=r-l+1,is[stot]=1;
}read(nb);
for(int i=1;i<=nb;i++) {
int l,r;read(l),read(r);
int now=pos[l];
for(int j=18;~j;j--) if(ml[fa[now][j]]>=r-l+1) now=fa[now][j];
t[now].push_back(posb[i]=++stot);
len[stot]=r-l+1;
}
for(int x=1;x<=stot;x++) {
int pre=x,L=t[x].size();sort(t[x].begin(),t[x].end(),cmp);
for(int v,i=0;i<L;i++) {
v=t[x][i];add(pre,v);
if(!is[v]) pre=v,len[v]=0;
}lst[x]=pre;
}
for(int x=2;x<=stot;x++) if(par[x]) add(lst[par[x]],x);
int q;read(q);for(int i=1,x,y;i<=q;i++) read(x),read(y),add(posa[x],posb[y]);
}
void solve() {
queue<int > q;ll cnt=0,ans=0;while(!q.empty()) q.pop();
for(int i=1;i<=stot;i++) if(!d[i]) q.push(i);
while(!q.empty()) {
int x=q.front();q.pop();cnt++;
for(int v,i=head[x];i;i=e[i].nxt) {
v=e[i].to;dis[v]=max(dis[v],dis[x]+len[v]);
if(!(--d[v])) q.push(v);ans=max(ans,dis[v]);
}
}write(cnt==stot?ans:-1ll);
}
void clear() {
for(int i=1;i<=stot;i++) {
memset(tr[i],0,sizeof tr[i]);
memset(fa[i],0,sizeof fa[i]);
par[i]=ml[i]=len[i]=dis[i]=d[i]=lst[i]=pos[i]=is[i]=head[i]=0;
t[i].clear();
}tot=0;stot=lstp=1;
}
int main() {
int T;read(T);while(T--) build(),solve(),clear();
return 0;
}
[LOJ3049] [十二省联考 2019] 字符串问题的更多相关文章
- LOJ3049 [十二省联考2019] 字符串问题 【后缀自动机】【倍增】【拓扑排序】
题目分析: 建出后缀自动机,然后把A串用倍增定位到后缀自动机上,再把B串用倍增定位到后缀自动机上. SAM上每个点上的A串根据长度从小到大排序,建点,依次连边. 再对于SAM上面每个点,连到儿子的边, ...
- [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增
题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...
- 【BZOJ5496】[十二省联考2019]字符串问题(后缀树)
[BZOJ5496][十二省联考2019]字符串问题(后缀树) 题面 BZOJ 洛谷 题解 首先显然可以把具有支配关系的串从\(A\)到\(B\)连一条有向边,如果\(B_i\)是\(A_j\)的前缀 ...
- P5284 [十二省联考2019]字符串问题
这是一道涵盖了字符串.图论.数据结构三个方面的综合大题. 把这道题放在D1T2的人应该拖出去打 前置芝士 首先,您至少要会topsort. 其次,如果您只想拿个暴力分,字符串Hash就足够了:如果您想 ...
- Luogu P5284 [十二省联考2019]字符串问题
好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...
- 洛谷P5284 [十二省联考2019]字符串问题 [后缀树]
传送门 思路 设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度. 然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建 ...
- 洛谷.5284.[十二省联考2019]字符串问题(后缀自动机 拓扑 DP)
LOJ BZOJ 洛谷 对这题无话可说,确实比较...裸... 像dls说的拿拓扑和parent树一套就能出出来了... 另外表示BZOJ Rank1 tql... 暴力的话,由每个\(A_i\)向它 ...
- 【题解】Luogu P5284 [十二省联考2019]字符串问题
原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长 ...
- Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)
先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...
随机推荐
- Lwip:原生态的Linux socket应用如何移植到Lwip上
lwIP - A Lightweight TCP/IP stack 在上一篇中,我们了解到在OpenFastPath上如何移植原生态的Linux Socket应用程序,那么,对于另外一个老牌的小型TC ...
- 一文拆解Faas的真实案例
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文来自腾讯云技术沙龙,本次沙龙主题为Serverless架构开发与SCF部署实践 刘敏洁:具有多年云计算行业经验,曾任职于华为.UClou ...
- Docker 在Windows上的安装
1. 软件从Docker官网下载,进行安装,安装后,能看到如下界面. 2. 安装后,查看Docker 版 本信息. 3. 配置加速器 (1)选择setting. (2)依次选择,并填写自己的加速器地址 ...
- 反爬虫和抗DDOS攻击技术实践
导语 企鹅媒体平台媒体名片页反爬虫技术实践,分布式网页爬虫技术.利用人工智能进行人机识别.图像识别码.频率访问控制.利用无头浏览器PhantomJS.Selenium 进行网页抓取等相关技术不在本文讨 ...
- 笨办法学Python - 习题4: Variables and Names
1.习题 4: 变量(variable)和命名 学习目标:了解Python中变量的定义,学习定义简明易记的变量名 变量:变量是存储内存中的值,就是每定义一个变量就会在内存中开辟一个空间.基于变量的类型 ...
- [朴孝敏][Sketch]
歌词来源:http://music.163.com/#/song?id=406907303 作曲 : Ryan S. Jhun/August Rigo/Denzil Remedios [作曲 : Ry ...
- excel中如何将时间戳转换为日期格式
https://www.cnblogs.com/xueluozhangxin/p/5868225.html =TEXT((B2/1000+8*3600)/86400+70*365+19,"y ...
- 在虚拟机下安装Ubuntu
目录: 1.安装虚拟机 2.在虚拟下安装Ubuntu 本文将按照目录分两步来讲一下在虚拟机下安装Ubuntu.第一步是安装虚拟机,第二步是在虚拟机下安装Ubuntu. 安装虚拟机 下载虚拟机链接以及激 ...
- Bag类课后作业
20162316 Bag课后作业 下面小标题都是码云链接 实现代码 import java.util.Arrays; public class Bag implements BagInterface ...
- Java 面试 --- 3
上一篇,我们给出了大概35个题目,都是基础知识,有童鞋反映题目过时了,其实不然,这些是基础中的基础,但是也是必不可少的,面试题目中还是有一些基础题目的,我们本着先易后难的原则,逐渐给出不同级别的题目, ...