题目链接:

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

首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可。

但即使忽略判断前缀的时间,光是连边的时间就会爆炸,显然不能暴力连边。

对于前缀不好解决,可以将字符串翻转然后变成判断是否是后缀。

可以发现对于后缀自动机的$parent$树,每个节点是子树内所有节点的后缀。

那么我们可以利用$parent$树来优化建图过程,将树上每个点向子节点连边。

对于每个$A$串和$B$串在后缀自动机上匹配出对应节点,如果是$A$串就新建节点并将$parent$树上的对应节点连向它,如果是$B$串就新建节点连向$parent$树上的对应节点。

对于$80\%$的数据,因为保证$B$串比$A$串短,所以对于$parent$树上的一个节点既有出点又有入点是合法的($100\%$的部分最后再说)。

但现在只解决了建图的问题,字符串在后缀自动机上匹配的时间复杂度依旧无法保证,如何找到每个$A,B$串对应的节点?

因为$[l,r]$的串一定是$[1,r]$的串的后缀,所以$[l,r]$的串在$parent$树上对应的节点一定是$[1,r]$的串对应节点的祖先,那么我们可以记录一下所有$[1,r]$的串在$parent$树上对应的节点,然后倍增往上跳来找到$[l,r]$对应的节点。

对于$100\%$的数据,不保证$B$串比$A$串短,那么就可能存在一个$B$串比一个$A$串长,但这两个串在$parent$树上对应的节点相同。如果像上述方式连边的话,就会导致这个$B$串能转移到$A$串。

对于这种情况,我们将连在$parent$树上同一点的所有串存起来,按长度从小到大为第一关键字、先$B$串后$A$串为第二关键字排序,将$parent$树上每个点与父节点之间的边拆开,在这两点之间建一串点,分别与排完序的$A,B$串新建点相连,再将这一串点依次相连,这样有了上下制约关系就不会导致上述情况发生了。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int len[1200010];
int pre[1200010];
int tr[1200010][26];
int fa[1200010][19];
int num[200010];
int val[1200010];
int head[1200010];
int to[1400010];
int next[1400010];
int cnt;
int last;
int T;
int tot;
char ch[200010];
int na,nb;
int n,m;
int l,r;
int x,y;
int a[200010];
int b[200010];
int d[1200010];
queue<int>q;
int vis[1200010];
ll f[1200010];
int sum;
struct lty
{
int len,num,opt;
lty(){}
lty(int LEN,int NUM,int OPT){len=LEN,num=NUM,opt=OPT;}
bool operator <(lty a)const
{
return len==a.len?num>a.num:len<a.len;
}
};
vector<lty>v[400010];
inline void add(int x,int y)
{
next[++tot]=head[x];
head[x]=tot;
to[tot]=y;
d[y]++;
}
inline void insert(int x,int id)
{
int p=last;
int np=++cnt;
memset(tr[np],0,sizeof(tr[np]));
last=np;
len[np]=len[p]+1;
num[id]=np;
for(;p&&!tr[p][x];p=pre[p])
{
tr[p][x]=np;
}
if(!p)
{
pre[np]=1;
}
else
{
int q=tr[p][x];
if(len[q]==len[p]+1)
{
pre[np]=q;
}
else
{
int nq=++cnt;
memset(tr[nq],0,sizeof(tr[nq]));
len[nq]=len[p]+1;
pre[nq]=pre[q];
memcpy(tr[nq],tr[q],sizeof(tr[q]));
pre[q]=pre[np]=nq;
for(;p&&tr[p][x]==q;p=pre[p])
{
tr[p][x]=nq;
}
}
}
}
inline void build()
{
for(int i=2;i<=cnt;i++)
{
fa[i][0]=pre[i];
}
for(int j=1;j<=18;j++)
{
for(int i=2;i<=cnt;i++)
{
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
inline int ST(int x,int dis)
{
for(int i=18;i>=0;i--)
{
if(len[fa[x][i]]>=dis)
{
x=fa[x][i];
}
}
return x;
}
inline void clear()
{
for(int i=1;i<=sum;i++)
{
v[i].clear();
}
}
inline void solve()
{
scanf("%s",ch+1);
n=strlen(ch+1);
for(int i=1;i<=n;i++)
{
insert(ch[n-i+1]-'a',i);
}
build();
sum=cnt;
scanf("%d",&na);
for(int i=1;i<=na;i++)
{
scanf("%d%d",&l,&r);
a[i]=++cnt;
int p=ST(num[n-l+1],r-l+1);
v[p].push_back(lty(r-l+1,a[i],0));
val[a[i]]=r-l+1;
}
scanf("%d",&nb);
for(int i=1;i<=nb;i++)
{
scanf("%d%d",&l,&r);
b[i]=++cnt;
int p=ST(num[n-l+1],r-l+1);
v[p].push_back(lty(r-l+1,b[i],1));
}
for(int i=2;i<=sum;i++)
{
sort(v[i].begin(),v[i].end());
int sz=v[i].size();
int now=pre[i];
for(int j=0;j<sz;j++)
{
cnt++;
add(now,cnt);
if(!v[i][j].opt)
{
add(cnt,v[i][j].num);
}
else
{
add(v[i][j].num,cnt);
}
now=cnt;
}
add(now,i);
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(a[x],b[y]);
}
for(int i=1;i<=cnt;i++)
{
f[i]=val[i];
if(!d[i])
{
q.push(i);
vis[i]=1;
}
}
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now];i;i=next[i])
{
if(f[to[i]]<f[now]+val[to[i]])
{
f[to[i]]=f[now]+val[to[i]];
}
d[to[i]]--;
if(!d[to[i]])
{
q.push(to[i]);
vis[to[i]]=1;
}
}
}
ll ans=0;
for(int i=1;i<=cnt;i++)
{
if(!vis[i])
{
printf("-1\n");
clear();
return;
}
ans=max(ans,f[i]);
}
printf("%lld\n",ans);
clear();
}
inline void init()
{
cnt=last=1,tot=0;
memset(head,0,sizeof(head));
memset(to,0,sizeof(to));
memset(val,0,sizeof(val));
memset(num,0,sizeof(num));
memset(pre,0,sizeof(pre));
memset(tr[1],0,sizeof(tr[1]));
memset(next,0,sizeof(next));
memset(len,0,sizeof(len));
memset(d,0,sizeof(d));
memset(vis,0,sizeof(vis));
memset(f,0,sizeof(f));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
solve();
}
}

[十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增的更多相关文章

  1. 洛谷.5284.[十二省联考2019]字符串问题(后缀自动机 拓扑 DP)

    LOJ BZOJ 洛谷 对这题无话可说,确实比较...裸... 像dls说的拿拓扑和parent树一套就能出出来了... 另外表示BZOJ Rank1 tql... 暴力的话,由每个\(A_i\)向它 ...

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

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

  3. BZOJ 5496: [2019省队联测]字符串问题 (后缀数组+主席树优化建图+拓扑排序)

    题意 略 分析 考场上写了暴力建图40分溜了-(结果只得了30分) 然后只要优化建边就行了 首先给出的支配关系无法优化,就直接A向它支配的B连边. 考虑B向以B作为前缀的所有A连边,做一遍后缀数组,两 ...

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

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

  5. 【BZOJ5495】[十二省联考2019]异或粽子(主席树,贪心)

    [BZOJ5495][十二省联考2019]异或粽子(主席树,贪心) 题面 BZOJ 洛谷 题解 这不是送分题吗... 转异或前缀和,构建可持久化\(Trie\). 然后拿一个堆维护每次的最大值,每次如 ...

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

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

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

    好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...

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

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

  9. LOJ3049 [十二省联考2019] 字符串问题 【后缀自动机】【倍增】【拓扑排序】

    题目分析: 建出后缀自动机,然后把A串用倍增定位到后缀自动机上,再把B串用倍增定位到后缀自动机上. SAM上每个点上的A串根据长度从小到大排序,建点,依次连边. 再对于SAM上面每个点,连到儿子的边, ...

随机推荐

  1. jQuery 父iframe与子iframe 相互调用传值

    来自:https://blog.csdn.net/wd4871/article/details/50517597 侵删 父页面中的iframe :如下 <iframe name="su ...

  2. echarts饼图配置模板

    var option = { title:{ text:'完成人构成分析--申报', //标题的样式 textSytle:{ //颜色 color : '#FF0000', //粗细 // fontW ...

  3. JS table内容转成二维数组,支持colspan和rowspan

    思路:1.先初始化colspan的数据到数组2.根据rowspan和colspan计算th和td的矩阵二次填充数组 说明:需要引用到第三方库jQuery,table中的th和td行和列跨度必须正确 & ...

  4. DVWA 黑客攻防演练(二)暴力破解 Brute Froce

    暴力破解,简称"爆破".不要以为没人会对一些小站爆破.实现上我以前用 wordpress 搭建一个博客开始就有人对我的站点进行爆破.这是装了 WordfenceWAF 插件后的统计 ...

  5. ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...

  6. 第五周课后作业——热门软件创新分析+附加题1&附加题3

    鉴于我们寝室都热衷于手游,所以本次热门软件创新分析我就来分析一下几款热门的抽卡型手游.   阴阳师(后文简称YYS)——剧情画风唯美,配音引人入胜 作为网易公司研发的一款3D日式和风回合制游戏,YYS ...

  7. c/c++ 继承与多态 容器与继承1

    问题:类B公有继承类A,类A有虚函数fun,类B覆盖了虚函数fun,有一个std::vector<A>,添加A的对象a,和B的对象b,到这个容器里,然后从vector里取出来,使用对象a. ...

  8. 我的第一个python web开发框架(25)——定制ORM(一)

    在开始编写ORM模块之前,我们需要先对db_helper进行重构,因为ORM最终生成的sql是需要转给db_helper来执行的,所以拥有一个功能完善.健壮的数据库操作类是非常必要的. 这是项目原db ...

  9. supervisor management kafka zookeeper

    # cat kafka.ini [program:kafka] command=/usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/ ...

  10. 使用time+dd测试硬盘读写速度

    命令:time dd if=/dev/zero bs=1M count=2048 of=direct_2G   此命令为在当前目录下新建一个2G的文件 Demo如下: 写速度: time dd if= ...