内存限制:1024 MiB
时间限制:5000 ms
现有一个字符串 S S S。
Tiffany 将从中划出 n a n_a na 个子串作为 A 类串,第 i i i 个( 1 ≤ i ≤ n a 1\leq i\leq n_a 1≤i≤na)为 A i = S ( l a i , r a i ) A_i = S\left( la_i, ra_i\right) Ai=S(lai,rai)。
类似地,Yazid 将划出 n b n_b nb 个子串作为 B 类串,第 i i i 个( 1 ≤ i ≤ n b 1\leq i\leq n_b 1≤i≤nb)为 B i = S ( l b i , r b i ) B_i = S\left( lb_i, rb_i\right) Bi=S(lbi,rbi)。
现额外给定 m m m 组支配关系,每组支配关系 ( x , y ) \left( x,y\right) (x,y) 描述了第 x x x 个 A 类串支配第 y y y 个 B 类串。
求一个长度最大的目标串 T T T,使得存在一个串 T T T 的分割 T = t 1 + t 2 + ⋯ + t k T=t_1 + t_2 +\dots +t_k T=t1+t2+⋯+tk( k ≥ 0 k\geq 0 k≥0)满足:
方便起见,你只需要输出这个最大的长度即可。
特别地,如果存在无限长的目标串(即对于任意一个正整数 n n n,都存在一个满足限制的长度超过 n n n 的串),请输出 − 1 -1 −1。
1 ≤ ∣ S ∣ ≤ 2 × 1 0 5 1\leq \lvert S\rvert\leq 2\times 10^5 1≤∣S∣≤2×105, n a , n b ≤ 2 × 1 0 5 n_a , n_b\leq 2\times 10^5 na,nb≤2×105, m ≤ 2 × 1 0 5 m\leq 2\times 10^5 m≤2×105
数据千万条,清空第一条。
多测不清空,爆零两行泪。
题意大概就是将A往支配的B连边,B往它作为前缀的A连边的最长路
对于后一部分我们可以反串后建立SAM,建立parent树,然后对于A,B利用倍增找到它所对应的节点
这样可能一个节点对应很多个A和B,所以在每个节点上我们对其按照长度排序,然后B往下一个B连边,A向长度小于等于它的第一个B连反向边,特别的我们可以设立一个特殊点,使其作为B的功能且长度最短
然后对于parent树上的父亲和儿子节点,我们将父亲长度最长的B和儿子的特殊点相连
跑拓扑即可
#include
using namespace std;
const int N=2e6+5;long long ans,dis[N];
int T,fa[N][20],len[N],lst,sz,n,id[N],na,nb,a[N];
int b[N],cnt,t,hd[N],d[N],V[N],nx[N],h[N],m,ch[N][26];
char s[N];bool isa[N];vectorg[N];queueq;
void add(int u,int v){
nx[++t]=hd[u];d[V[hd[u]=t]=v]++;
}
int init(int x){
len[++sz]=x;fa[sz][0]=isa[sz]=0;
memset(ch[sz],0,sizeof ch[sz]);return sz;
}
void build(int x){
int p=lst,np=init(len[p]+1);
while(p && !ch[p][x])
ch[p][x]=np,p=fa[p][0];
if (!p) fa[np][0]=1;
else{
int q=ch[p][x];
if (len[q]==len[p]+1) fa[np][0]=q;
else{
int nq=init(len[p]+1);
fa[nq][0]=fa[q][0];
memcpy(ch[nq],ch[q],sizeof ch[q]);
fa[q][0]=fa[np][0]=nq;
while(p && ch[p][x]==q)
ch[p][x]=nq,p=fa[p][0];
}
}
lst=np;
}
void find(bool ty){
int x,y;scanf("%d%d",&x,&y);
y=y-x+1;x=id[x];
for (int i=18;~i;i--)
if (len[fa[x][i]]>=y)
x=fa[x][i];
isa[++cnt]=ty;len[cnt]=y;
g[x].push_back(cnt);
}
bool cmp(int A,int B){
return len[A]>len[B]||(len[A]==len[B]&&isa[A]>isa[B]);
}
int main(){
for (scanf("%d",&T);T--;ans=0){
scanf("%s",s+1);n=strlen(s+1);sz=0;lst=init(0);
for (int i=n;i;i--) build(s[i]-'a'),id[i]=lst;
for (int j=1;(1<