对反串建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. Linux如何使用shell命令检测PHP木马防止脚本木马的破坏

    1.一句话查找PHP木马 代码如下 # find / -name "*.php" |xargs egrep "phpspy|c99sh|milw0rm|eval\(gun ...

  2. activemq jmx

    增加: -Djava.rmi.server.hostname=<IP addr>

  3. Matrix: Matrix的,postScale(), postTranslate()方法

    Matrix的操作,总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在Android的API里都提供了set, post和pre三种操作方 ...

  4. 用户Ip地址和百度地图api接口获取用户地理位置(经纬度坐标,城市)

    <?php   //获取用户ip(外网ip 服务器上可以获取用户外网Ip 本机ip地址只能获取127.0.0.1) function getip(){     if(!empty($_SERVE ...

  5. springboot集成调用Azkaban

    springboot集成调用Azkaban 一. 说明 1.Azkaban是由Linkedin公司推出的一个批量工作流任务调度器,主要用于在一个工作流内以一个特定的顺序运行一组工作和流程,它的配置是通 ...

  6. 一个小时学会Git(转载)

    ---恢复内容开始--- 一个小时学会Git     最近要与部门同事一起做技术分享,我选择了Git,因为Git 是一种在全球范围都广受欢迎的版本控制系统.在开发过程中,为了跟踪代码,文档,项目等信息 ...

  7. ElasticSearch——冷热(hot&warm)架构部署

    背景 最近在做订单数据存储到ElasticSearch,考虑到数据量比较大,采用冷热架构来存储,每月建立一个新索引,数据先写入到热索引,通过工具将3个月后的索引自动迁移到冷节点上. ElasticSe ...

  8. es6 fetch方法请求接口

    fetch(url, { method: 'post', headers: { 'Content-type': 'application/x-www-form-urlencoded; charset= ...

  9. 记EXSI虚拟机CentOS7断电无法启动修复过程

    参考:https://msd.misuland.com/pd/3148108429789233656 EXSI6.7安装虚拟机CentOS7.5 1804 断电后启动页面进度条很慢 最后出现如下提示 ...

  10. 【ARTS】01_33_左耳听风-201900624~201900630

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...