思路
设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度。
然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建出图来就完事了。
显然可以用数据结构得到两点之间是否有边,于是就获得了40分的好成绩。
考虑优化这个建图,字符串也就那么几个数据结构,那就后缀树吧。
有了后缀树,可以发现\(k\)会向\(k\)所在的节点的子树连边,注意不包括\(k\)自己的节点。
那么自己节点怎么办呢?把在这里的所有串拆开然后按长度排一下序即可。
然后就是用虚点优化,随便搞就好了。
这省选题好像也不难
代码先咕着,下午再写。
uptade:下午由于数组开小狂WA,怒调3小时无果,还因为size(),lower_bound()等函数炸掉而一脸懵逼……
数组就应该能开多大开多大……
代码
#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 1204040
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__zz=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register int x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__zz]=x%10+48,x/=10);
while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
char s[sz];
int N,n,m;
int la[sz],ra[sz],lb[sz],rb[sz];
int fa[sz],len[sz],ch[sz][27],cnt=1,lst=1;
int edp[sz];
void insert(int c)
{
int cur=++cnt,p=lst;lst=cur;
len[cur]=len[p]+1;
while (p&&!ch[p][c]) ch[p][c]=cur,p=fa[p];
if (!p) return (void)(fa[cur]=1);
int q=ch[p][c];
if (len[p]+1==len[q]) return (void)(fa[cur]=q);
int t=++cnt;
memcpy(ch[t],ch[q],sizeof(ch[q]));
len[t]=len[p]+1;fa[t]=fa[q];
while (p!=-1&&ch[p][c]==q) ch[p][c]=t,p=fa[p];
fa[q]=fa[cur]=t;
}
void calcEndPos(){int x=1;drep(i,N,1) x=ch[x][s[i]-'a'+1],edp[i]=x;}
struct hh{int t,nxt;}edge[sz];
int head[sz],ecnt;
void make_edge(int f,int t){edge[++ecnt]=(hh){t,head[f]};head[f]=ecnt;}
int Fa[sz][25];
void dfs1(int x,int fa){Fa[x][0]=fa;rep(i,1,20) Fa[x][i]=Fa[Fa[x][i-1]][i-1];go(x) dfs1(edge[i].t,x);}
vector<pii>va[sz],vb[sz];
void ins(int id,int lenth,int p)
{
drep(i,20,0) if (Fa[p][i]&&len[Fa[p][i]]>=lenth) p=Fa[p][i];
if (id<=n) va[p].push_back(MP(lenth,id));
else vb[p].push_back(MP(lenth,id));
}
int son[sz],cc;
int deg[sz];
struct hhh{int f,t,w,nxt;}E[sz];
int Head[sz],Ecnt;
void MakeEdge(int f,int t,int w){++deg[t];E[++Ecnt]=(hhh){f,t,w,Head[f]};Head[f]=Ecnt;}
int lastt=0;
void dfs2(int x)
{
sort(va[x].begin(),va[x].end());
int nxt=cc+1,las;cc+=va[x].size()+1;las=cc;
drep(i,(int)va[x].size()-1,0) MakeEdge(nxt+i,nxt+i+1,0),MakeEdge(nxt+i,va[x][i].sec,va[x][i].fir);
rep(i,0,(int)vb[x].size()-1)
{
int pos=lower_bound(va[x].begin(),va[x].end(),MP(vb[x][i].fir,-1))-va[x].begin();
MakeEdge(vb[x][i].sec,nxt+pos,0);
}
go(x) dfs2(edge[i].t),MakeEdge(las,son[edge[i].t],0);
son[x]=nxt;
}
ll dp[sz];
bool vis[sz];
void work()
{
cin>>(s+1);
N=strlen(s+1);
drep(i,N,1) insert(s[i]-'a'+1);
calcEndPos();
rep(i,2,cnt) make_edge(fa[i],i);
dfs1(1,0);
int K,x,y;
read(n);
rep(i,1,n) read(la[i],ra[i]),ins(i,ra[i]-la[i]+1,edp[la[i]]),dp[i]=ra[i]-la[i]+1;
read(m);
rep(i,1,m) read(lb[i],rb[i]),ins(i+n,rb[i]-lb[i]+1,edp[lb[i]]);
read(K);
while (K--) read(x,y),MakeEdge(x,y+n,0);
cc=n+m;
dfs2(1);
queue<int>q;
ll ans=0;
rep(i,1,cc) if (!deg[i]) q.push(i);
while (!q.empty())
{
int x=q.front();q.pop();vis[x]=1;
chkmax(ans,dp[x]);
for (int i=Head[x];i;i=E[i].nxt)
{
int v=E[i].t;--deg[v];chkmax(dp[v],dp[x]+E[i].w);
if (!deg[v]) q.push(v);
}
}
bool flg=1;
rep(i,1,cc) flg&=vis[i];
printf("%lld\n",flg?ans:-1ll);
rep(i,1,N) s[i]='\0',edp[i]=0;
rep(i,1,n) la[i]=ra[i]=0;
rep(i,1,m) lb[i]=rb[i]=0;
rep(i,1,cnt) { fa[i]=len[i]=head[i]=0; rep(j,1,26) ch[i][j]=0; }
rep(i,1,cc) Head[i]=0,va[i].clear(),vb[i].clear(),son[i]=0,deg[i]=0,dp[i]=0,vis[i]=0;
ecnt=cc=Ecnt=0;cnt=lst=1;
}
int main()
{
file();
int T;read(T);
while (T--) work();
return 0;
}