LOJ

BZOJ

洛谷

对这题无话可说,确实比较...裸...

像dls说的拿拓扑和parent树一套就能出出来了...

另外表示BZOJ Rank1 tql...


暴力的话,由每个\(A_i\)向它能支配的\(B_j\)连边,再由\(B_j\)向它能匹配的\(A_k\)(是\(A_k\)的前缀)连边,拓扑DP就可以了。

正解就是优化建图方式。

把串反过来,\(B_j\)能匹配\(A_k\)就是\(B_j\)是\(A_k\)的后缀,换句话说\(B_j\)能匹配\(parent\)树中它子树的所有\(A_k\)。所以由每个\(A_i,B_j\)向\(parent\)树中连边即可。

但是如果没有\(|A_i|\geq|B_j|\)的限制,处在同一节点的\(B_j\)可能就不是\(A_i\)的后缀了。

我们对该节点上的串按长度排个序,\(B_j\)从小的向大的连边,\(A_i\)由最后一个\(\leq\)它的\(B_j\)向它连边,类似前缀和优化建图,就可以了。(注意建的是反图,这里说的是正向的边)

求一个子串在SAM的哪个节点上,可以倍增,见CF666E

顺便粘一篇题解...


除了数组开小了,1A,开心.jpg。

//16102ms	127.4MB
#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
#define BIT 18
#define gc() getchar()
typedef long long LL;
const int N=2e5+5,N2=N<<2,M=1e6+5;//N2=4n not 3n =-= M=m+na+nb+2n int La[N],Ra[N],Lb[N],Rb[N],Enum,H[N2],nxt[M],to[M],dgr[N2],q[N2];
LL f[N2];
char s[N];
struct Node
{
int len,p;
bool operator <(const Node &a)const
{
return len<a.len||(len==a.len&&p>a.p);
}
};
std::vector<Node> vec[N<<1]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline void AE(int v,int u)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, ++dgr[v];
}
struct Suffix_Automaton
{
#define S N<<1
int bit,las,tot,son[S][26],fa[S],F[S][BIT+1],len[S],H[S],nxt[S],pos[S];
#undef S
inline void AE_Tree(int u,int v)
{
nxt[v]=H[u], H[u]=v;
}
inline int Find(int l,int p)
{
p=pos[p];
for(int i=bit; ~i; --i) if(len[F[p][i]]>=l) p=F[p][i];
return p;
}
void Insert(int c)
{
int p=las,np=++tot; len[las=np]=len[p]+1;
for(; p&&!son[p][c]; p=fa[p]) son[p][c]=np;
if(!p) fa[np]=1;
else
{
int q=son[p][c];
if(len[q]==len[p]+1) fa[np]=q;
else
{
int nq=++tot; len[nq]=len[p]+1;
memcpy(son[nq],son[q],sizeof son[q]);
fa[nq]=fa[q], fa[q]=fa[np]=nq;
for(; son[p][c]==q; p=fa[p]) son[p][c]=nq;
}
}
}
void DFS1(int x,int dep)
{
bit=std::max(bit,dep);
for(int i=1; 1<<i<=dep; ++i) F[x][i]=F[F[x][i-1]][i-1];
for(int v=H[x]; v; v=nxt[v]) F[v][0]=x, DFS1(v,dep+1);
}
void DFS_Clear(int x,int dep)
{
for(int i=1; 1<<i<=dep; ++i) F[x][i]=0;
for(int v=H[x]; v; v=nxt[v]) DFS_Clear(v,dep+1);
}
void Build(char *s,int n)
{
las=tot=bit=1;
for(int i=1; i<=n; ++i) Insert(s[i]-'a'), pos[i]=las;
for(int i=2; i<=tot; ++i) AE_Tree(fa[i],i);
DFS1(1,1);
int mx=bit; bit=1;
while(1<<bit<mx) ++bit;
}
#define IsA(x) (x>tot&&x<=tot+na)
void Build2(int na,int nb)
{
for(int i=1; i<=tot; ++i)
{
if(!vec[i].size()) {AE(fa[i],i); continue;}
std::sort(vec[i].begin(),vec[i].end());
const std::vector<Node> &v=vec[i];
int las=fa[i];
for(int j=0,l=v.size(); j<l; ++j)
{
int now=v[j].p; AE(las,now);
if(!IsA(now)) las=now;
}
AE(las,i);
}
}
void Clear()
{
DFS_Clear(1,1);
for(int i=1; i<=tot; ++i) std::vector<Node>().swap(vec[i]);
memset(H,0,tot+1<<2), memset(son,0,(sizeof son[0])*(tot+1));
}
}sam;
#define GetLen(x) (x>tot&&x<=tot+na?Ra[x-tot]-La[x-tot]+1:0)
void Solve()
{
scanf("%s",s+1);
int len=strlen(s+1); std::reverse(s+1,s+len+1);
sam.Build(s,len); int na=read(),tot=sam.tot;
for(int i=1; i<=na; ++i) Ra[i]=len-read()+1,La[i]=len-read()+1;
int nb=read();
for(int i=1; i<=nb; ++i) Rb[i]=len-read()+1,Lb[i]=len-read()+1;
for(int m=read(),u; m--; ) u=read(),AE(u+tot,read()+tot+na);
for(int i=1,l; i<=na; ++i) l=Ra[i]-La[i]+1, vec[sam.Find(l,Ra[i])].push_back((Node){l,i+tot});
for(int i=1,l; i<=nb; ++i) l=Rb[i]-Lb[i]+1, vec[sam.Find(l,Rb[i])].push_back((Node){l,i+tot+na});
sam.Build2(na,nb); int Tot=tot+na+nb; int h=0,t=0;
for(int i=1; i<=Tot; ++i) if(!dgr[i]) q[t++]=i, f[i]=GetLen(i);
LL ans=0;
while(h<t)
{
int x=q[h++]; ans=std::max(ans,f[x]);
for(int i=H[x],v; i; i=nxt[i])
{
v=to[i], f[v]=std::max(f[v],f[x]);
if(!--dgr[v]) f[v]+=GetLen(v), q[t++]=v;
}
}
printf("%lld\n",t>=Tot?ans:-1ll);
sam.Clear(), Enum=0, memset(H,0,Tot+1<<2), memset(dgr,0,Tot+1<<2), memset(f,0,Tot+1<<3);
} int main()
{
for(int T=read(); T--; Solve());
return 0;
}

洛谷.5284.[十二省联考2019]字符串问题(后缀自动机 拓扑 DP)的更多相关文章

  1. 洛谷P5284 [十二省联考2019]字符串问题 [后缀树]

    传送门 思路 设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度. 然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建 ...

  2. [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增

    题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...

  3. 洛谷P5284 [十二省联考2019]字符串问题(SAM+倍增+最长路)

    题面 传送门 题解 首先,我们把串反过来,那么前缀就变成后缀,建一个\(SAM\).我们发现一个节点的后缀是它的所有祖先 那么我们是不是直接按着\(parent\)树建边就可以了呢? 显然不是.我们假 ...

  4. 洛谷.5283.[十二省联考2019]异或粽子(可持久化Trie 堆)

    LOJ 洛谷 考场上都拍上了,8:50才发现我读错了题=-= 两天都读错题...醉惹... \(Solution1\) 先求一遍前缀异或和. 假设左端点是\(i\),那么我们要在\([i,n]\)中找 ...

  5. 洛谷P5289 [十二省联考2019]皮配(01背包)

    啊啊啊边界判错了搞死我了QAQ 这题是一个想起来很休闲写起来很恶心的背包 对于\(k=0\)的情况,可以发现选阵营和选派系是独立的,对选城市选阵营和学校选派系分别跑一遍01背包就行了 对于\(k> ...

  6. 洛谷 5291 [十二省联考2019]希望(52分)——思路+树形DP

    题目:https://www.luogu.org/problemnew/show/P5291 考场上写了 16 分的.不过只得了 4 分. 对于一个救援范围,其中合法的点集也是一个连通块. 2n 枚举 ...

  7. 【BZOJ5496】[十二省联考2019]字符串问题(后缀树)

    [BZOJ5496][十二省联考2019]字符串问题(后缀树) 题面 BZOJ 洛谷 题解 首先显然可以把具有支配关系的串从\(A\)到\(B\)连一条有向边,如果\(B_i\)是\(A_j\)的前缀 ...

  8. [LOJ3049] [十二省联考 2019] 字符串问题

    题目链接 LOJ:https://loj.ac/problem/3049 洛谷:https://www.luogu.org/problemnew/show/P5284 BZOJ:https://www ...

  9. P5284 [十二省联考2019]字符串问题

    这是一道涵盖了字符串.图论.数据结构三个方面的综合大题. 把这道题放在D1T2的人应该拖出去打 前置芝士 首先,您至少要会topsort. 其次,如果您只想拿个暴力分,字符串Hash就足够了:如果您想 ...

随机推荐

  1. python之路day05--字典的增删改查,嵌套

    字典dic 数据类型划分:可变数据类型,不可变数据类型 不可变数据类型:元组,bool,int str -->可哈希可变数据类型:list,dict,set --> 不可哈希 dict k ...

  2. consul kv使用介绍

    有两种方法与Consul K/V交互的方式 HTTP API Consul KV CLI WEB访问 命令行使用 帮助命令:consul kv --help 列出所有kv:consul kv get ...

  3. DirectX11 With Windows SDK--13 动手实现一个简易Effects框架、阴影效果绘制

    前言 到现在为止,所有的教程项目都没有使用Effects11框架类来管理资源.因为在D3DCompile API (#47)版本中,如果你尝试编译fx_5_0的效果文件,会收到这样的警告: X4717 ...

  4. [再寄小读者之数学篇](2014-10-18 利用 Lagrange 中值定理求极限)

    试求 $$\bex \vlm{n}n^2\sex{x^\frac{1}{n}-x^\frac{1}{n+1}},\quad x>0. \eex$$ 解答: $$\beex \bea \mbox{ ...

  5. @JsonView的使用,entity中指定向前台返回哪些字段

    使用步骤: 1.使用接口来声明多个视图 2.在值对象的get方法上指定视图 3.在Controller方法上指定视图

  6. burp suite 基础入门超详细教程

    介绍: 都是我个人了解到的信息,,分享给大家 欢迎指正 burp suite 被誉为web安全工具中的瑞士军刀. 大家知道,瑞士军刀,都是体积小,功能强悍,.西方军队的标配.说这么多,只是想强调这款工 ...

  7. 013_RomanToInteger

    #####solution1####faster#### def romanToInt(s): d={ 'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, ...

  8. (一)校园信息通微信小程序从前端到后台整和笔记

    前段时间接触了微信小程序,现在回过头来做一些笔记. 先上效果图 后台数据管理界面(PHP) 校园信息通微信小程序前端界面 下面先简单的说一下怎样部署一个微信小程序 首先是前端 微信小程序有它专门的开发 ...

  9. 关于MySQL中的8个 character_set 变量

    https://blog.csdn.net/sun8112133/article/details/79921734 本篇会简单介绍在 MySQL 中关于 8个 character_set 变量的基本作 ...

  10. XML,json,ajax

    一.XML 1.概述:XML全称为Extensible Markup Language, 意思是可扩展的标记语言 2.版本:W3C在1998年2月发布1.0版本:W3C在2004年2月发布1.1版本, ...