[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串长度 ...
随机推荐
- 自动化运维工具saltstack05 -- 之salt-ssh模式
salt-ssh模式 1.说明: salt-ssh即通过ssh得方式进行管理,不需要安装salt-minion, salt-ssh 用的是sshpass进行密码交互的. 2.salt-ssh得局限性 ...
- lua字符串类型
Lua中字符串结构体的定义是: typedef union TString { L_Umaxalign dummy; /* ensures maximum alignment for strings ...
- 004 --Mysql中的锁的问题
死锁 死锁是指两个或多个事务在同一个资源上相互占用, 并请求锁定对方占用的资源, 从而导致恶性循环的现象. 当多个事务试图以不同顺序锁定资源时, 就可能产生死锁.死锁发生以后, 只有部分或者完全回滚其 ...
- PHP核心技术——异常和错误处理
PHP只有手动抛出异常后才能捕获异常 $a = null; try { $a = 5/0; echo $a,PHP_EOL; } catch (exception $e) { $e -> get ...
- 微信小程序-帝国cms会员系统调用
在用户->管理会员字段,增加如下字段:openidsession_keylsktokennicknameheadimg设置用户名长度然后,在系统,系统变最设置,用户设置,将注册用户名设置长度改成 ...
- Java字符串分割
java中字符串的分割函数,split("你想要分割的字符", 你想要最多分割为多少段,正整数) 注意事项: 1.分割特殊字符考虑转义字符的使用.如: . \ | 2.第二个参数: ...
- Hadoop源码编译环境搭建
准备工具: maven 3.0.0版本或者更高版本(配置中心库) protocbuff 2.5.0 http://www.zlib.net/ git bash(Windows环境可以用此工具执行编译命 ...
- PASSWORD MySQL 5.6.21-1ubuntu14.04_amd64
/***************************************************************************** The main idea is that ...
- git实践笔记
title: git实践笔记 date: 2016-10-15 18:40:26 tags: [Git] categories: [Tool,Git] --- 概述 本文记录常用 git 的功能和命令 ...
- React.js - 入门
React.js - 第1天 1. React简介 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 ...