# bzoj 5496

40分代码：

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ull unsigned long long
#define seed 131131
using namespace std;
char s[200005];
int l[200005];
int r[200005];
ull p[200005];
ull has[200005];
bool vis[200005];
int T;
struct Edge
{
int nxt;
int to;
}edge[1000005];
int cnt=1;
int na,nb,m;
bool used[10005];
int inr[10005];
int dis[10005];
void init()
{
memset(inr,0,sizeof(inr));
memset(vis,0,sizeof(vis));
cnt=1;
}
{
edge[cnt].to=r;
}
int spfa(int x)
{
memset(used,0,sizeof(used));
memset(dis,0,sizeof(dis));
queue <int> M;
M.push(x);
used[x]=1;
dis[x]=r[x]-l[x]+1;
int ans=dis[x];
while(!M.empty())
{
int u=M.front();
M.pop();
{
int to=edge[i].to;
if(to>na)
{
continue;
}
if(dis[to]<dis[u]+r[to]-l[to]+1)
{
dis[to]=dis[u]+r[to]-l[to]+1;
ans=max(ans,dis[to]);
if(!used[to])
{
used[to]=1;
M.push(to);
}
}
}
used[u]=0;
}
return ans;
}
bool tsort()
{
queue <int> M;
int tot=0;
for(int i=1;i<=na;i++)
{
if(!inr[i])
{
M.push(i);
tot++;
}
}
while(!M.empty())
{
int u=M.front();
M.pop();
{
int to=edge[i].to;
if(to>na)
{
continue;
}
inr[to]--;
if(inr[to]==0)
{
M.push(to);
tot++;
}
}
}
if(tot==na)
{
return 1;
}
return 0;
}
int main()
{
//    freopen("string.in","r",stdin);
//    freopen("string.out","w",stdout);
scanf("%d",&T);
while(T--)
{
init();
scanf("%s",s+1);
int len=strlen(s+1);
has[0]=0;
p[0]=1;
for(int i=1;i<=len;i++)
{
has[i]=has[i-1]*seed+s[i]-'a'+1;
p[i]=p[i-1]*seed;
}
scanf("%d",&na);
for(int i=1;i<=na;i++)
{
scanf("%d%d",&l[i],&r[i]);
}
scanf("%d",&nb);
for(int i=1;i<=nb;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ull hh=has[y]-has[x-1]*p[y-x+1];
for(int j=1;j<=na;j++)
{
if(r[j]-l[j]+1>=y-x+1)
{
if(has[l[j]+y-x]-has[l[j]-1]*p[y-x+1]==hh)
{
if(na!=1)
{
}else
{
vis[i]=1;
}
}
}
}
}
scanf("%d",&m);
bool flag=0;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(na!=1)
{
y+=na;
}else
{
if(vis[y])
{
flag=1;
}
}

}
if(na==1)
{
if(flag)
{
printf("-1\n");
continue;
}else
{
printf("%d\n",r[1]-l[1]+1);
continue;
}
}
for(int i=1;i<=na;i++)
{
{
int to=edge[j].to;
{
int too=edge[t].to;
inr[too]++;
}
}
}
if(!tsort())
{
printf("-1\n");
continue;
}
int ret=0;
for(int i=1;i<=na;i++)
{
ret=max(ret,spfa(i));
}
printf("%d\n",ret);
}
}

（据说可以后缀数组+st表+主席树优化建图搞，不过窝不会...）

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#define ll long long
using namespace std;
struct Edge
{
int nxt;
int to;
int val;
}edge[800005];
struct node
{
int po,ilen;
node (){}
node (int a,int b):po(a),ilen(b){}
friend bool operator < (node a,node b)
{
return a.po==b.po?a.ilen<b.ilen:a.po<b.po;
}
};
set <node> S;
int cnt=1;
int tranc[400005][27];
int vis[400005];
int l[400005],r[400005],pos[400005];
int va[800005];
int pre[400005];
bool used[800005];
int tf[400005];//字符串中某个位置向后缀自动机中节点的映射
int len[400005];
int inr[800005];
char ch[400005];
ll dis[800005];
int f[400005][25];
vector <int> v[400005];
vector <node> rS[400005];
int tot,las,temptot;
int T,n;
int na,nb,m;
void init()
{
for(int i=1;i<=temptot;i++)rS[i].clear(),v[i].clear(),vis[i]=pre[i]=len[i]=0,memset(tranc[i],0,sizeof(tranc[i]));
S.clear();
tot=las=cnt=1;
}
{
edge[cnt].to=r;
edge[cnt].val=w;
}
void ins(int c,int o)
{
int nwp=++tot;
len[nwp]=len[las]+1;
tf[o]=nwp;
int lsp;
for(lsp=las;lsp&&!tranc[lsp][c];lsp=pre[lsp])tranc[lsp][c]=nwp;
if(!lsp)pre[nwp]=1;
else
{
int lsq=tranc[lsp][c];
if(len[lsq]==len[lsp]+1)pre[nwp]=lsq;
else
{
int nwq=++tot;
memcpy(tranc[nwq],tranc[lsq],sizeof(tranc[lsq]));
pre[nwq]=pre[lsq];
pre[lsq]=pre[nwp]=nwq;
len[nwq]=len[lsp]+1;
while(lsp&&tranc[lsp][c]==lsq)tranc[lsp][c]=nwq,lsp=pre[lsp];
}
}
las=nwp;
}
void buildtree()
{
for(int i=2;i<=tot;i++)v[pre[i]].push_back(i),f[i][0]=pre[i];
f[1][0]=1;
}
int Jump(int st,int di)
{
for(int i=20;i>=0;i--)if(len[f[st][i]]>=di&&f[st][i]!=1)st=f[st][i];
if(S.find(node(st,di))==S.end())S.insert(node(st,di)),vis[st]++;
return st;
}
void rebuild(int x,int fx)
{
if(x==1){for(int i=0;i<v[x].size();i++)rebuild(v[x][i],x);return;}
sort(rS[x].begin(),rS[x].end());
int now=0;
for(int i=1;i<rS[x].size();i++)if(rS[x][i].po!=rS[x][i-1].po){now=i;break;}
int las=x;
while(vis[x]>1)
{
tot++,vis[x]--;
pos[rS[x][now].ilen]=tot;
for(int i=now+1;i<rS[x].size();i++)
{
if(rS[x][i].po!=rS[x][i-1].po){now=i;break;}
else pos[rS[x][i].ilen]=tot;
}
las=tot;
}
for(int i=0;i<v[x].size();i++)rebuild(v[x][i],las);
}
ll spfa()
{
queue <int> M;
M.push(1);
dis[1]=0;
int cct=1;
ll ans=0;
while(!M.empty())
{
int u=M.front();
M.pop();
ans=max(ans,dis[u]+(ll)va[u]);
{
int to=edge[i].to;
dis[to]=max(dis[u]+(ll)edge[i].val,dis[to]);
inr[to]--;
if(!inr[to])M.push(to),cct++;
}
}
if(cct==tot)return ans;
else return -1;
}
int main()
{
scanf("%d",&T);
while(T--)
{
init();
scanf("%s",ch+1);
n=strlen(ch+1);
for(int i=n;i>=1;i--)ins(ch[i]-'a'+1,i);
buildtree();
for(int i=1;i<=20;i++)for(int j=1;j<=tot;j++)f[j][i]=f[f[j][i-1]][i-1];
scanf("%d",&na);
for(int i=1;i<=na;i++)
{
scanf("%d%d",&l[i],&r[i]);
pos[i]=Jump(tf[l[i]],r[i]-l[i]+1);
}
scanf("%d",&nb);
for(int i=na+1;i<=na+nb;i++)
{
scanf("%d%d",&l[i],&r[i]);
pos[i]=Jump(tf[l[i]],r[i]-l[i]+1);
}
for(int i=1;i<=na+nb;i++)rS[pos[i]].push_back(node(r[i]-l[i]+1,i));
temptot=tot;
rebuild(1,0);
for(int i=1;i<=na;i++)va[pos[i]]=r[i]-l[i]+1;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
y+=na;
}