[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串长度 ...
随机推荐
- 《杜增强讲Unity之Tanks坦克大战》8-子弹碰撞处理
8 子弹碰撞处理 为了处理子弹打到坦克的伤害我们在这里新建一个Shell.cs 子弹有两种情况,碰到坦克炸开,没有碰到坦克则过2s子弹销毁. void Start () { Destroy (game ...
- Hacknet 玩后感
这款游戏的主题是黑客模拟.玩家需要帮助雇主搞定各种乱七八糟的需求. 你需要使用各种工具和各种linux命令行来获取对方电脑的Root权限.然后就是各种增删改查... 解密部分设计的太过简单,导致玩的时 ...
- Flink架构分析之RPC详解
主要抽象 Flink RPC 框架主要抽象了RpcService,RpcEndpoint,RpcGateway,RpcServer这几个接口,具体实现可以采用多种方式,比如:akka,netty Rp ...
- [文章存档]Kudu 的 Debug Console 窗口如何查看更多文件
链接:https://docs.azure.cn/zh-cn/articles/azure-operations-guide/app-service-web/aog-app-service-web-h ...
- ReLU——Deep Sparse Rectifier Neural Networks
1. 摘要 ReLU 相比 Tanh 能产生相同或者更好的性能,而且能产生真零的稀疏表示,非常适合自然就稀疏的数据. 采用 ReLU 后,在大量的有标签数据下,有没有无监督预训练模型取得的最好效果是一 ...
- [BUAA软工]第0次个人作业
[BUAA软工]第0次个人作业 本次作业所属课程 : 2019BUAA软件工程 本次作业要求: 第0次个人作业 我在本课程的目标: 熟悉软件工程流程,规范开发习惯 本次作业的帮助: 熟悉课程流程 Pa ...
- Gogoing 场景调研(补)
一.典型用户 蜗居在学校的大学生 二.场景描述 编号 用户故事 故事价值 (点数) 1 作为一名大学生,只知道学习 2 经常打游戏而无所事事的大学生 1.背景 (1)典型用户:张晨建 (2)用户的需求 ...
- “吃神么,买神么”的第一个Sprint计划(第五天)
“吃神么,买神么”项目Sprint计划 ——5.25 星期一(第五天)立会内容与进度 摘要:logo2出来了,修改过不一样的风格,组内总体评价可以,但是颜色要改,色调没注意,统一决定改成与背景色一致 ...
- 蜗牛慢慢爬 LeetCode 9. Palindrome Number [Difficulty: Easy]
题目 Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could nega ...
- js+Canvas 利用js 实现浏览器保存图片到本地
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...