題面見: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());
}
}