原题传送门

我用sa做的本题 (码量似乎有点大)

先对原串建sa

考虑如何建图:

一开始每个以某个后缀都单独用一个链表存储。用merge函数依次将lcp为n~1的后缀的链表合并,当这个lcp为某个a串时候,在链表中插入a。当这个lcp为某个b串时候,以b开始的后缀所在的链表中的元素就是其所对应的a串(见merging函数)

现在每个b对应的a的编号都是链表中一段连续的区间

珂以用线段树优化建图

最后跑一下拓扑排序即可得出答案

#include <bits/stdc++.h>
#define N 1000005
#define M 16000005
#define ll long long
using namespace std;
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register ll x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline ll Max(register ll a,register ll b)
{
return a>b?a:b;
}
struct edge{
int to,next;
}e[M];
int head[N],cnte=1,degree[N],w[N],nt;
inline void add_edge(register int u,register int v)
{
e[++cnte]=(edge){v,head[u]};
head[u]=cnte;
++degree[v];
}
inline void cleargraph()
{
memset(w,0,sizeof(w));
memset(degree,0,sizeof(degree));
memset(head,0,sizeof(head));
cnte=1;
}
ll dp[N];
int q[N],qh,qt;
inline ll topsort()
{
qh=qt=0;
memset(dp,0,sizeof(dp));
for(register int i=1;i<=nt;++i)
if(!degree[i])
q[++qt]=i;
ll ans=0;
while(qh<qt)
{
int u=q[++qh];
dp[u]+=w[u];
ans=Max(ans,dp[u]);
for(register int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
dp[v]=Max(dp[v],dp[u]);
if(!--degree[v])
q[++qt]=v;
}
}
return qt<nt?-1LL:ans;
}
int n,sizem;
char s[N];
int rak[N],sa[N],tp[N],tex[N],height[N];
inline void Qsort()
{
for(register int i=0;i<=sizem;++i)
tex[i]=0;
for(register int i=1;i<=n;++i)
++tex[rak[i]];
for(register int i=1;i<=sizem;++i)
tex[i]+=tex[i-1];
for(register int i=n;i>=1;--i)
sa[tex[rak[tp[i]]]--]=tp[i];
}
inline void sa_build()
{
memset(tp,0,sizeof(tp));
memset(rak,0,sizeof(rak));
sizem=30;
for(register int i=1;i<=n;++i)
rak[i]=s[i]-'a'+1,tp[i]=i;
Qsort();
for(register int w=1,p=0;p<n;sizem=p,w<<=1)
{
p=0;
for(register int i=1;i<=w;++i)
tp[++p]=n-w+i;
for(register int i=1;i<=n;++i)
if(sa[i]>w)
tp[++p]=sa[i]-w;
Qsort();
swap(tp,rak);
rak[sa[1]]=p=1;
for(register int i=2;i<=n;++i)
rak[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
}
}
inline void getheight()
{
int k=0;
for(register int i=1;i<=n;++i)
{
if(k)
--k;
int j=sa[rak[i]-1];
while(s[i+k]==s[j+k])
++k;
height[rak[i]]=k;
}
}
struct Unionset{
int f[N];
inline void makeset(register int n)
{
for(register int i=1;i<=n;++i)
f[i]=i;
}
inline int find(register int x)
{
return f[x]==x?f[x]:f[x]=find(f[x]);
}
inline void merge(register int x,register int y)
{
if(find(x)!=find(y))
f[f[x]]=f[y];
}
};
struct ListNode{
int l,r;
ListNode():l(-1),r(-1){}
};
ListNode* listNode=nullptr;
inline void clearListNodes()
{
if(listNode!=nullptr)
delete[] listNode;
listNode=new ListNode[N];
}
struct List{
int head,tail;
List():head(-1),tail(-1){}
List(int node):head(node),tail(node){}
List(int l,int r):head(l),tail(r){}
List operator +(const List& other){
if(tail==-1)
return other;
if(other.head==-1)
return *this;
listNode[tail].r=other.head;
listNode[other.head].l=tail;
return List(head,other.tail);
}
};
int na,nb,la[N],ra[N],lb[N],rb[N];
List lst[N];
vector<int> merges[N],alen[N],blen[N];
Unionset us;
int invl[N],invr[N],ppos[N],seq[N];
inline void merging()
{
clearListNodes();
for(register int i=1;i<=n;++i)
lst[i]=List();
for(register int i=0;i<=n;++i)
{
merges[i].clear();
alen[i].clear();
blen[i].clear();
}
for(register int i=1;i<n;++i)
merges[height[i+1]].push_back(i);
for(register int i=1;i<=na;++i)
alen[ra[i]-la[i]+1].push_back(i);
for(register int i=1;i<=nb;++i)
blen[rb[i]-lb[i]+1].push_back(i);
us.makeset(n);
for(register int len=n;len>=0;--len)
{
for(register int i=0;i<merges[len].size();++i)
{
int k=merges[len][i];
int u=us.find(k),v=us.find(k+1);
List tmp=lst[u]+lst[v];
us.merge(u,v);
lst[us.find(u)]=tmp;
}
for(register int i=0;i<alen[len].size();++i)
{
int a=alen[len][i];
int u=us.find(rak[la[a]]);
lst[u]=List(a)+lst[u];
}
for(register int i=0;i<blen[len].size();++i)
{
int b=blen[len][i];
int v=us.find(rak[lb[b]]);
invl[b]=Max(0,lst[v].head);
invr[b]=Max(0,lst[v].tail);
}
}
for(register int i=1,u=lst[us.find(1)].head;i<=na;++i,u=listNode[u].r)
{
if(u==-1)
break;
seq[i]=u;
ppos[u]=i;
}
ppos[0]=-1;
for(register int i=1;i<=nb;++i)
{
invl[i]=ppos[invl[i]];
invr[i]=ppos[invr[i]];
}
}
inline void input()
{
scanf("%s",s+1);
n=strlen(s+1);
na=read();
for(register int i=1;i<=na;++i)
la[i]=read(),ra[i]=read();
nb=read();
for(register int i=1;i<=nb;++i)
lb[i]=read(),rb[i]=read();
cleargraph();
int m=read();
for(register int i=1;i<=m;++i)
{
int x=read(),y=read();
add_edge(x,na+y);
}
}
int tot=0,ls[N],rs[N];
inline void seg_build(register int &x,register int l,register int r)
{
if(l==r)
{
x=seq[l];
return;
}
else
x=++tot;
int mid=l+r>>1;
seg_build(ls[x],l,mid);
seg_build(rs[x],mid+1,r);
add_edge(x,ls[x]),add_edge(x,rs[x]);
}
inline void seg_addedge(register int x,register int l,register int r,register int b,register int L,register int R)
{
if(L<=l&&r<=R)
{
add_edge(b+na,x);
return;
}
int mid=l+r>>1;
if(L<=mid)
seg_addedge(ls[x],l,mid,b,L,R);
if(R>mid)
seg_addedge(rs[x],mid+1,r,b,L,R);
}
inline void buildsegtr()
{
tot=na+nb;
int root;
seg_build(root,1,na);
for(register int i=1;i<=nb;++i)
{
if(invl[i]<0)
continue;
seg_addedge(root,1,na,i,invl[i],invr[i]);
}
nt=tot;
}
inline ll solve()
{
input();
sa_build();
getheight();
merging();
buildsegtr();
for(register int i=1;i<=na;++i)
w[i]=ra[i]-la[i]+1;
return topsort();
}
int T;
int main()
{
T=read();
while(T--)
write(solve()),puts("");
return 0;
}

【题解】Luogu P5284 [十二省联考2019]字符串问题的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. 【题解】Luogu P5291 [十二省联考2019]希望

    ytq鸽鸽出的题真是毒瘤 原题传送门 题目大意: 有一棵有\(n\)个点的树,求有多少方案选\(k\)个联通块使得存在一个中心点\(p\),所有\(k\)个联通块中所有点到\(p\)的距离都\(\le ...

  8. 【题解】Luogu P5283 [十二省联考2019]异或粽子

    原题传送门 看见一段的异或和不难想到要做异或前缀和\(s\) 我们便将问题转化成:给定\(n\)个数,求异或值最靠前的\(k\)对之和 我们珂以建一个可持久化01trie,这样我们就珂以求出每个值\( ...

  9. 【题解】Luogu P5290 [十二省联考2019]春节十二响

    原题传送门 每个点维护一个堆,表示这个点及其子树所需的每段内存的空间 搜索时从下向上做启发式合并堆中信息,最后根节点堆中所有内存空间之和就是答案 #include <bits/stdc++.h& ...

随机推荐

  1. apache-2.4.6 mod_bw-0.92 实现限速上传或下载

    下载 mod_bw  wget http://ivn.cl/files/source/mod_bw-0.92.tgz 解压到mod_bw tar -zxvf mod_bw-0.92.tgz -C mo ...

  2. express 随笔

    #express 1.使用Express 应用生成器 npm install express-generator -g 2.创建一个命名为 myapp 的应用 express myapp 3.安装所有 ...

  3. k8s-No.3-pod进阶

    本章目录 pod环境变量env pod的资源限制resources pod的健康检查-探针 pod的imagepullsecrets 一   pod-env 环境变量就是系统或者程序运行时的预定义的参 ...

  4. 在vue中使用lang="scss"出现报错解决思路

    最近在学习vue框架,使用lang="scss" 出现如下错误: This dependency was not found: * !!vue-style-loader!css-l ...

  5. volatile有什么用?能否用一句话描述volatile的应用场景

    volatile保证内存可见性和禁止指令重排.volatile用于多线程环境下的单次操作(单次读或者单次写).volatile关键字不能提供原子性.     volatile关键字为实例域的同步访问提 ...

  6. vue跳转到外部链接

    <span @click="see('http://xxxx">点击跳转到xxx</span> 方法:(调用函数) See (e) { window.loc ...

  7. 学习h264 的语法规则,如何才能看懂H264 的官方文档

    1. 今天想查h264 的帧率,查找资料如下: 首先要解析sps,得到两个关键的数值: num_units_in_tick, time_scale fps=time_scale/num_units_i ...

  8. JVM入门到放弃之基本概念

    1. 基本概念 jvm 是可运行Java代码的假想计算机,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回收堆和一个存储方法域. jvm 是运行在操作系统之上的,屏蔽了与具体操作系统平台相关的信息 ...

  9. Git常用功能记录

    1. git查看某个文件的修改历史 git log --pretty 然后使用下面的命令可列出文件的所有改动历史,注意,这里着眼于具体的一个文件,而不是git库,如果是库,那改动可多了去了- git ...

  10. 如何增加Ubuntu交换空间swap

    如何增加Ubuntu交换空间swap 1  使用命令查看系统内swap分区大小 green@green:~$ free -m total used free shared buff/cache ava ...