题解
这道题目也太重工业了吧。。。
胡题 (20 min) ,写题 (5 days) ,还没写出来 ,我只能爪巴。
不想调了,写篇题解记录一下思路。
就是你给反串建出 ( ext{SAM}) 之后在考虑直接在树上建图,然后跑一个 ( ext{top}) 就可以了。
代码
(0pts) ,样例都过了,想调的人可以帮我调一下。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=4e5+5;
int ls,na,nb,m,id[N];char s[N];
struct Sub{int l,r,len;}a[N],b[N];
int tot=0,tag[N][2],f[N<<1],res;
struct Tree{
struct Edge{int nxt,from,to;}e[N<<1];int fir[N<<1],deg[N<<1],size=0;
void add(int u,int v){e[++size]=(Edge){fir[u],u,v},deg[v]++,fir[u]=size;}
}t1,t2;
struct SAM{
int tot,lst;
struct Node{
int len,fa[20],go[26];
vector<pair<int,pair<int,int> > > bag;
}tr[N<<1];
void clear(){
tot=lst=1;
for(int i=0;i<(N<<1);++i){
tr[i].len=tr[i].fa[0]=0,tr[i].bag.clear();
memset(tr[i].go,0,sizeof(tr[i].go));
}
}
void insert(int x){
int u=lst,now=lst=++tot;
tr[now].len=tr[u].len+1;
while(u&&!tr[u].go[x])
tr[u].go[x]=now,u=tr[u].fa[0];
if(!u) return tr[now].fa[0]=1,void();
int v=tr[u].go[x];
if(tr[u].len+1==tr[v].len)
return tr[now].fa[0]=v,void();
int w=++tot;tr[w]=tr[v];
tr[w].len=tr[u].len+1;
tr[v].fa[0]=tr[now].fa[0]=w;
while(u&&tr[u].go[x]==v)
tr[u].go[x]=w,u=tr[u].fa[0];
}
}sam;
void dfs(int u,int anc){
sort(sam.tr[u].bag.begin(),sam.tr[u].bag.end());
for(int i=0;i<(int)sam.tr[u].bag.size();++i){
pair<int,pair<int,int> > tmp=sam.tr[u].bag[i];
if(i&&tmp.first==sam.tr[u].bag[i-1].first)
tag[tmp.second.first][tmp.second.second]=tot;
else{
tag[tmp.second.first][tmp.second.second]=++tot;
if(anc) t2.add(anc,tot),anc=tot;
}
}
for(int i=t1.fir[u];i;i=t1.e[i].nxt) dfs(t1.e[i].to,anc);
}
void init(){
tot=t1.size=t2.size=res=0;
memset(s,0,sizeof(s));
memset(tag,0,sizeof(tag));
memset(t1.fir,0,sizeof(t1.fir));
memset(t1.deg,0,sizeof(t1.deg));
memset(t2.fir,0,sizeof(t2.fir));
memset(t2.deg,0,sizeof(t2.deg));
for(int i=0;i<(N<<1);++i) f[i]=-1e18-7;
sam.clear();
}
bool top(){
queue<int> q;
f[tot+na+1]=0,q.push(tot+na+1);
for(int i=1;i<=tot+na;++i) if(!t2.deg[i]) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
res=max(res,f[u]);
// printf("%lld %lld
",u,f[u]);
for(int i=t2.fir[u];i;i=t2.e[i].nxt){
int v=t2.e[i].to;t2.deg[v]--;
if(v<=tot) f[v]=max(f[v],f[u]);
else f[v]=max(f[v],f[u]+a[v-tot].len);
if(!t2.deg[v]) q.push(v);
}
}
for(int i=1;i<=tot+na+1;++i) if(t2.deg[i]) return false;
return true;
}
void solve(){
scanf("%s",s+1),ls=strlen(s+1);
for(int i=ls;i>=1;--i){
sam.insert(s[i]-'a');
id[ls-i+1]=sam.tot;
}
for(int i=2;i<=sam.tot;++i){
t1.add(sam.tr[i].fa[0],i);
}
for(int j=1;j<20;++j){
for(int i=1;i<=sam.tot;++i)
sam.tr[i].fa[j]=sam.tr[sam.tr[i].fa[j-1]].fa[j-1];
}
scanf("%lld",&na);
for(int i=1;i<=na;++i){
scanf("%lld%lld",&a[i].r,&a[i].l);
a[i].l=ls-a[i].l+1,a[i].r=ls-a[i].r+1;
int u=id[a[i].r];a[i].len=a[i].r-a[i].l+1;
for(int j=19;j>=0;--j){
if(sam.tr[sam.tr[u].fa[j]].len>=a[i].len)
u=sam.tr[u].fa[j];
}
sam.tr[u].bag.push_back(make_pair(a[i].len,make_pair(i,0)));
}
scanf("%lld",&nb);
for(int i=1;i<=nb;++i){
scanf("%lld%lld",&b[i].r,&b[i].l);
b[i].l=ls-b[i].l+1,b[i].r=ls-b[i].r+1;
int u=id[b[i].r];b[i].len=b[i].r-b[i].l+1;
for(int j=19;j>=0;--j){
if(sam.tr[sam.tr[u].fa[j]].len>=b[i].len)
u=sam.tr[u].fa[j];
}
sam.tr[u].bag.push_back(make_pair(b[i].len,make_pair(i,1)));
}
dfs(1,0);
for(int i=1;i<=na;++i){
t2.add(tot+na+1,tot+i);
t2.add(tag[i][0],tot+i);
}
scanf("%lld",&m);
for(int i=1;i<=m;++i){
int u,v;scanf("%lld%lld",&u,&v);
t2.add(tot+u,tag[v][1]);
}
// for(int i=1;i<=t2.size;++i){
// printf("%lld %lld
",t2.e[i].from,t2.e[i].to);
// }
return printf("%lld
",top()?res:-1ll),void();
}
signed main(){
int T;cin>>T;
while(T--) init(),solve();
}
/*
1
abbaabbaab
4
1 5
4 7
6 9
8 10
3
1 6
10 10
4 6
5
1 2
1 3
2 1
3 3
4 1
*/