对反串建SAM弄出后缀树,每个b串通过倍增定位其在后缀树上对应的节点,根据其长度将节点拆开。然后每个a串也找到对应的节点,由该节点向表示a串的节点连边,再把所给的边连上跑拓扑排序即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 800010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int T,n,na,nb,m,son[N][26],fail[N],len[N],id[N],f[N][21],pos[N],cnt,last;
char s[N];
struct data{int l,r;
}a[N],b[N];
int p[N],degree[N],q[N],val[N],t;
ll F[N];
struct data2{int to,nxt;
}edge[N<<1];
vector<int> node[N];
void addedge(int x,int y){t++;degree[y]++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
int newnode(){cnt++;memset(son[cnt],0,sizeof(son[cnt]));fail[cnt]=len[cnt]=0;node[cnt].clear();return cnt;}
void ins(int c)
{
int x=newnode(),p=last;last=x;len[x]=len[p]+1;id[len[x]]=x;
while (!son[p][c]&&p) son[p][c]=x,p=fail[p];
if (!p) fail[x]=1;
else
{
int q=son[p][c];
if (len[p]+1==len[q]) fail[x]=q;
else
{
int y=newnode();
len[y]=len[p]+1;
memcpy(son[y],son[q],sizeof(son[q]));
fail[y]=fail[q],fail[q]=fail[x]=y;
while (son[p][c]==q) son[p][c]=y,p=fail[p];
}
}
}
int find(int x,int y)
{
for (int j=20;~j;j--) if (len[f[x][j]]>=y) x=f[x][j];
return x;
}
int find2(int x,int y)
{
if (len[x]<=y) return x;
for (int j=20;~j;j--) if (len[f[x][j]]>y) x=f[x][j];
return fail[x];
}
bool cmp(int x,int y){return b[x].r<b[y].r;}
ll topsort()
{
int head=0,tail=0;
for (int i=1;i<=cnt;i++)
{
F[i]=val[i];
if (!degree[i]) q[++tail]=i;
}
while (head<tail)
{
int x=q[++head];
for (int i=p[x];i;i=edge[i].nxt)
{
degree[edge[i].to]--;
F[edge[i].to]=max(F[edge[i].to],F[x]+val[edge[i].to]);
if (!degree[edge[i].to]) q[++tail]=edge[i].to;
}
}
if (tail<cnt) return -1;
ll ans=0;
for (int i=1;i<=cnt;i++) ans=max(ans,F[i]);
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read();
while (T--)
{
scanf("%s",s+1);
n=strlen(s+1);cnt=0;last=1;newnode();
for (int i=1;i<=n;i++) ins(s[n-i+1]-'a');
for (int i=1;i<=cnt;i++) f[i][0]=fail[i];f[1][0]=1;
for (int j=1;j<21;j++)
for (int i=1;i<=cnt;i++)
f[i][j]=f[f[i][j-1]][j-1];
na=read();
for (int i=1;i<=na;i++)
{
a[i].l=read(),a[i].r=read();
a[i].r=a[i].r-a[i].l+1;a[i].l=n-a[i].l+1;
}
nb=read();
for (int i=1;i<=nb;i++)
{
b[i].l=read(),b[i].r=read();
b[i].r=b[i].r-b[i].l+1;b[i].l=n-b[i].l+1;
int x=find(id[b[i].l],b[i].r);
node[x].push_back(i);
}
for (int i=1;i<=cnt;i++)
if (!node[i].empty())
{
sort(node[i].begin(),node[i].end(),cmp);
int last=fail[i];
for (int j=0;j<node[i].size();)
{
int x=node[i][j];
if (b[x].r==len[i])
{
for (;j<node[i].size();j++) pos[node[i][j]]=i;
break;
}
len[newnode()]=b[x].r;fail[cnt]=last;last=cnt;
while (j<node[i].size()&&b[node[i][j]].r==len[cnt]) pos[node[i][j]]=cnt,j++;
}
fail[i]=last;
}
for (int i=1;i<=cnt;i++) f[i][0]=fail[i];f[1][0]=1;
for (int j=1;j<21;j++)
for (int i=1;i<=cnt;i++)
f[i][j]=f[f[i][j-1]][j-1];
for (int i=1;i<=cnt+na;i++) F[i]=degree[i]=p[i]=val[i]=0;t=0;
for (int i=cnt+1;i<=cnt+na;i++) val[i]=a[i-cnt].r;
for (int i=2;i<=cnt;i++) addedge(fail[i],i);
for (int i=1;i<=na;i++) addedge(find2(id[a[i].l],a[i].r),cnt+i);
m=read();
for (int i=1;i<=m;i++)
{
int x=read(),y=read();
addedge(cnt+x,pos[y]);
}
cnt+=na;
cout<<topsort()<<endl;
}
return 0;
}

  

Luogu5284 十二省联考2019字符串问题(后缀树+拓扑排序)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长 ...

随机推荐

  1. TortoiseGit的安装与配置

    1. 简介 TortoiseGit是Tortoise提供的Git版本可视化工具,简化Git记忆命令行的过程,将命令行可视化. 2. 下载 官网:https://tortoisegit.org/down ...

  2. resin初识

    Resin初识 1. resin简介 刚入职的公司用的后台服务器是resin,故因此学习记录一下. resin是一个非常流行的web引用服务器,对servlet和jsp提供了良好的支持,自身采用jav ...

  3. linux listen()

    listen(等待连接) 相关函数 socket,bind,accept,connect表头文件 #include<sys/socket.h>定义函数 int listen(int s,i ...

  4. GO --- 将Reader 或者 ReadCloser 转化为 ReadSeeker

    原因: ReadSeeker 封装了Seek()方法,这个方法要求资源的任何位置都能被定位,例如存储在磁盘里文件,你可以随时读取文件的任意位置.而response.Body 是通过TCP连接从网络中读 ...

  5. sqlServer sa账号被锁定

    alter login sa with password = '123'  unlock, check_policy = off, check_expiration = off    一切搞定.. 1 ...

  6. OpenSL ES: 利用OpenSL ES播放一个存在于SDcard上的PCM文件

    native-lib.cpp #include <jni.h> #include <string> #include <SLES/OpenSLES.h> #incl ...

  7. Android Studio创建Module-库模块

    Android Studio创建Module-库模块   本文链接:https://blog.csdn.net/niuba123456/article/details/81049676 模块是源文件和 ...

  8. 123457123457#0#---------com.ppGame.SeaPuzzleGame73--前拼后广--宝宝海洋拼图pp

    com.ppGame.SeaPuzzleGame73--前拼后广--宝宝海洋拼图pp

  9. 第六章 Realm及相关对象——《跟我学Shiro》

    转发地址:https://www.iteye.com/blog/jinnianshilongnian-2022468 目录贴:跟我学Shiro目录贴 6.1 Realm [2.5 Realm]及[3. ...

  10. 通过命令行给 XenServer 打补丁

    安装 XenCenter 客户端,cmd 到 XenCenter 安装目录. 1.上传补丁到服务器,获得uuid xe patch-upload -s <服务器IP地址> -u root ...