题面见:https://www.luogu.com.cn/problem/P5284
题解
当年考的时候直接写了40暴力。。。
现在看了看,好像可以用后缀树优化建图
先倒着建一个SAM,然后再倍增定位每个区间
后缀树上的边就从父亲连向儿子,A连边向B
此时我们本来应该让B向其定位的区间连边的
但是一个点可能会对应多个区间,直接连边会出很多其他的问题
于是我们换一种思路,把定位在同一个点的区间按照长度排序,B排在A的前面
先从SAM上的点依次向这些点连边,遇到了B之后就再从B开始向后连边,这样就保证了连边的数量以及连通性
注意,向儿子连边时要用当前点的最后一个B来连边,如果直接用当前点来连边会导致后面的B区间无法与儿子连通
这种写法会好写很多
如果建出来的图有环就说明可以一直转圈得到无穷大的答案
如果不存在环就是一个DAG
最后DAG上DP求最大权路径的时候只把A点的权值算进去就可以了
本蒟蒻的第二道字符串大题。。。
代码:(虽然只有2.6KB,我也不知道为什么写了这么久。。。我太菜了)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
inline int gi()
{
char c;int num=0,flg=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
return num*flg;
}
#define N 200005
#define LOG 19
#define LL long long
int all;
int fir[4*N],to[5*N],nxt[5*N],ind[4*N],cnt;
char ss[N];
int fa[2*N],ch[2*N][26],len[2*N],las,tot;
int pos[2*N],f[LOG+1][2*N];
int tp[4*N];
vector<int> G[2*N];
int Glas[2*N];
queue<int> q;
LL dp[4*N];
void csh()
{
for(int i=1;i<=all;i++)
dp[i]=fir[i]=tp[i]=ind[i]=0;
for(int i=1;i<=tot;i++){
G[i].clear();
fa[i]=len[i]=pos[i]=Glas[i]=0;
for(int j=0;j<=LOG;j++)f[j][i]=0;
for(int j=0;j<26;j++)ch[i][j]=0;
}
las=tot=1;cnt=all=0;
}
void adde(int a,int b)
{
//printf("adde:%d %d\n",a,b);
to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;
ind[b]++;
}
void extend(int x)
{
int p,np,q,nq;
p=las;las=np=++tot;
len[np]=len[p]+1;
for(;p&&!ch[p][x];p=fa[p])ch[p][x]=np;
if(!p)fa[np]=1;
else{
q=ch[p][x];
if(len[q]==len[p]+1)fa[np]=q;
else{
nq=++tot;
len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));fa[nq]=fa[q];
for(;p&&ch[p][x]==q;p=fa[p])ch[p][x]=nq;
fa[q]=fa[np]=nq;
}
}
}
void add(bool flg)
{
int l=gi(),r=gi()-l+1;l=pos[l];
for(int i=LOG;i>=0;i--)if(len[f[i][l]]>=r)l=f[i][l];
tp[++all]=flg;len[all]=r;
G[l].push_back(all);
}
bool cmp(int x,int y){return len[x]<len[y]||(len[x]==len[y]&&tp[x]<tp[y]);}
LL solve()
{
for(int i=1;i<=all;i++)if(!ind[i])q.push(i);
int u;LL ret=0;
while(!q.empty()){
u=q.front();q.pop();
ret=max(ret,dp[u]+len[u]);
for(int v,p=fir[u];p;p=nxt[p]){
v=to[p];
dp[v]=max(dp[v],dp[u]+len[u]);
ind[v]--;if(!ind[v])q.push(v);
}
}
for(int i=1;i<=all;i++)if(ind[i])return -1;
return ret;
}
int main()
{
int T,n,na,nb,m,i,j,u,v;
T=gi();
while(T--){
csh();
scanf("%s",ss+1);
n=strlen(ss+1);
for(i=n;i>=1;i--){extend(ss[i]-'a');pos[i]=las;}
for(i=1;i<=tot;i++)f[0][i]=fa[i];
for(j=1;j<=LOG;j++)for(i=1;i<=tot;i++)f[j][i]=f[j-1][f[j-1][i]];
all=tot;
na=gi();for(i=1;i<=na;i++)add(1);
nb=gi();for(i=1;i<=nb;i++)add(0);
for(i=1;i<=tot;i++){
u=i;sort(G[i].begin(),G[i].end(),cmp);
for(j=0;j<(int)G[i].size();j++){
v=G[i][j];adde(u,v);
if(!tp[v])u=v;// OAA+BAA+BAA+BAA...
}
Glas[i]=u;// the last B
}
for(i=1;i<=all;i++)if(!tp[i])len[i]=0;
for(i=2;i<=tot;i++)adde(Glas[fa[i]],i);//.....BAA+son
m=gi();for(i=1;i<=m;i++){u=gi()+tot;v=gi()+tot+na;adde(u,v);}
printf("%lld\n",solve());
}
}