#7-10 TLE 已经修改了写法,用topsort找环,可是发现在solve()函数中,这几行:
for(int i=1;i<=ntot;++i){
for(int j=head[i];j;j=nxt[j]){
++rd[ver[j]];
}
}
跑的非常慢,#7的第一个点,本人输出中间结果发现边数(tot)和点数(ntot)在1e6左右并不大,在二分debug的时候确定了是这几行非常慢,不是其他的地方,请问这是为什么呢?实在不能理解
#include <bits/stdc++.h>
using namespace std;
void solve();
void init();
inline int read(){
int x=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')x=x*10+(c-'0'),c=getchar();
return x;
}
int main(){
int T;init();
freopen("string7.in","r",stdin);
scanf("%d",&T);
while(T--) solve();
return 0;
}
char s[200005];
int n;
int rk[400005],sa[400005],old[400005],tp[400005],bag[400005],m,hi[200005];
int rmq[200005][20],lg[200005];
void init(){
int now=0;
for(int i=1;i<=200000;++i){
lg[i]=now;
if((1<<now+1)==i) ++now;
}
return ;
}
int lcp(int x,int y){
if(x==y) return rmq[x][0];
int l=y-x;
return min(rmq[x+1][lg[l]],rmq[y-(1<<lg[l])+1][lg[l]]);
}
void get_sa(){
m=max(300,n);
memset(bag,0,sizeof bag);
for(int i=1;i<=n;++i) rk[i]=s[i],++bag[rk[i]];
for(int i=1;i<=m;++i) bag[i]+=bag[i-1];
for(int i=n;i>=1;--i) sa[bag[rk[i]]--]=i;
for(int w=1,p;;w<<=1){
p=0;
for(int i=1;i<=m;++i) bag[i]=0;
for(int i=n-w+1;i<=n;++i) tp[++p]=i;
for(int i=1;i<=n;++i) if(sa[i]>w) tp[++p]=sa[i]-w;
for(int i=1;i<=n;++i) ++bag[rk[tp[i]]];
for(int i=1;i<=m;++i) bag[i]+=bag[i-1];
for(int i=n;i>=1;--i) sa[bag[rk[tp[i]]]--]=tp[i];
p=1;
for(int i=1;i<=n;++i) old[i]=rk[i];
rk[sa[1]]=1;
for(int i=2;i<=n;++i)
if(old[sa[i]]==old[sa[i-1]] && old[sa[i]+w]==old[sa[i-1]+w])
rk[sa[i]]=p;
else rk[sa[i]]=++p;
if(p==n) break;
}
memset(hi,0,sizeof hi);
for(int i=1,k=0;i<=n;++i){
if(k) --k;
while(s[i+k]==s[sa[rk[i]-1]+k]) ++k;
hi[rk[i]]=k;
}
for(int i=0;i<=19;++i){
for(int j=1;j<=n;++j){
rmq[j][i]=0;
}
}
for(int i=1;i<=n;++i) rmq[i][0]=hi[i];
for(int i=1;i<=19;++i){
for(int j=1;j+(1<<i-1)<=n;++j){
rmq[j][i]=min(rmq[j][i-1],rmq[j+(1<<i-1)][i-1]);
}
}
return ;
}
struct node{
int ls,rs;
}tree[20000005];
int ntot;
int tot,head[10000005],nxt[20000005],ver[20000005],len[20000005];
inline void add_edge(int x,int y,int z){
++tot,nxt[tot]=head[x],head[x]=tot;
ver[tot]=y,len[tot]=z;
return ;
}
struct info{
int l,r;
}A[200005],B[200005];
int na,nb,root[200005];
vector<int>Len[200005];
void ins(int now,int l,int r,int x,int v){
if(l==r){
add_edge(now,v,0);
return ;
}
int mid=l+r>>1;
if(x<=mid){
head[ntot+1]=head[tree[now].ls];
tree[ntot+1]=tree[tree[now].ls];
tree[now].ls=++ntot;
add_edge(now,tree[now].ls,0);
ins(tree[now].ls,l,mid,x,v);
}
else {
head[ntot+1]=head[tree[now].rs];
tree[ntot+1]=tree[tree[now].rs];
tree[now].rs=++ntot;
add_edge(now,tree[now].rs,0);
ins(tree[now].rs,mid+1,r,x,v);
}
return ;
}
void build(){
memset(root,0,sizeof root);
ntot=na;
root[n+1]=++ntot;
for(int i=n;i>=1;--i){
int S=Len[i].size();
root[i]=++ntot;
tree[root[i]]=tree[root[i+1]];
for(int j=0;j<S;++j){
ins(root[i],1,n,rk[A[Len[i][j]].l],Len[i][j]);
}
}
return ;
}
int xx,vv;
void link(int now,int l,int r,int L,int R){
if(!now) return ;
if(l==L && r==R){
add_edge(xx,now,vv);
return ;
}
int mid=l+r>>1;
if(R<=mid) link(tree[now].ls,l,mid,L,R);
else if(L>=mid+1) link(tree[now].rs,mid+1,r,L,R);
else link(tree[now].ls,l,mid,L,mid),
link(tree[now].rs,mid+1,r,mid+1,R);
return ;
}
int flag=0,ed,rd[10000005];
long long dp[10000005];
queue<int>q;
void solve(){
scanf("%s",s+1);ntot=tot=0;
n=strlen(s+1);flag=0;
for(int i=1;i<=n;++i) Len[i].clear();
get_sa();
scanf("%d",&na);
for(int i=1;i<=na;++i)
A[i].l=read(),A[i].r=read(),
Len[A[i].r-A[i].l+1].push_back(i);
build();
scanf("%d",&nb);
for(int i=1;i<=nb;++i) B[i].l=read(),B[i].r=read();
scanf("%d",&m);int x,y,l,r,mid,L,R,lim;
for(int i=1;i<=m;++i){
x=read(),y=read();
lim=B[y].r-B[y].l+1;
l=1,r=rk[B[y].l];
while(l<r){
mid=l+r>>1;
if(lcp(mid,rk[B[y].l])>=lim) r=mid;
else l=mid+1;
}
L=l;
l=rk[B[y].l],r=n;
while(l<r){
mid=l+r+1>>1;
if(lcp(rk[B[y].l],mid)>=lim) l=mid;
else r=mid-1;
}
R=l;
xx=x,vv=A[x].r-A[x].l+1;
link(root[lim],1,n,L,R);
}
ed=++ntot;
for(int i=1;i<=na;++i) add_edge(i,ed,A[i].r-A[i].l+1);
for(int i=1;i<=ntot;++i) dp[i]=0ll,rd[i]=0;
for(int i=1;i<=ntot;++i){
for(int j=head[i];j;j=nxt[j]){
++rd[ver[j]];
}
}
for(int i=1;i<=ntot;++i)
if(!rd[i]) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=nxt[i]){
dp[ver[i]]=max(dp[ver[i]],dp[u]+1ll*len[i]);
--rd[ver[i]];
if(!rd[ver[i]]) q.push(ver[i]);
}
}
for(int i=1;i<=ntot;++i) if(rd[i]) flag=1;
if(!flag) printf("%lld\n",dp[ed]);else printf("-1\n");
for(int i=1;i<=ntot;++i) tree[i].ls=tree[i].rs=0;
for(int i=1;i<=ntot;++i) head[i]=0;
return ;
}