题目分析:

建出后缀自动机,然后把A串用倍增定位到后缀自动机上,再把B串用倍增定位到后缀自动机上。

SAM上每个点上的A串根据长度从小到大排序,建点,依次连边。

再对于SAM上面每个点,连到儿子的边,同时连到儿子的最小A串的边。

对于m组关系,建立x连到y定位到的SAM上的点的边,同时连y所能匹配的到定位到的点上的最短字符串的边。

然后跑拓扑排序就行了。

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ; char str[maxn];
int na,nb,len,m;
int la[maxn],ra[maxn],lb[maxn],rb[maxn]; int lst=,nxt[maxn<<][],fa[maxn<<],num=,maxlen[maxn<<],st[maxn];
int lk[maxn],bh[maxn],maxnum;
vector<pair<int,int> > g[maxn*];
vector<int> chain[maxn<<];
int in[maxn*];
long long dis[maxn*]; int RMQ[maxn<<][],nowmax; void buildRMQ(){
RMQ[][] = ;
for(int i=;i<=num;i++) RMQ[i][] = fa[i];
for(int k=;(<<k)<=num;k++){
nowmax = k;
for(int i=;i<=num;i++) RMQ[i][k] = RMQ[RMQ[i][k-]][k-];
}
} int findhhh(int spp,int len){
for(int i=nowmax;i>=;i--)if(maxlen[RMQ[spp][i]]>len) spp=RMQ[spp][i];
return spp;
} void init(){
for(int i=;i<=num;i++) for(int j=;(<<j)<=num;j++)RMQ[i][j] = ;
for(int i=;i<=num;i++){
for(int j=;j<;j++)nxt[i][j] = ;
fa[i] = ; maxlen[i] = ;
chain[i].clear();
}
for(int i=;i<=len;i++) st[i] = ;
for(int i=;i<=nb;i++)lk[i] = ;
for(int i=;i<=na;i++) bh[i] = ;
for(int i=;i<=maxnum+;i++)g[i].clear(),in[i] = ;
lst = ; num = ; maxnum = ;
} queue<int> que;
void topu(){
int sz = ;
for(int i=;i<=maxnum+;i++) dis[i] = -1e18;
for(int i=;i<=maxnum+;i++)
if(!in[i]) que.push(i),sz++;
dis[] = ;
while(!que.empty()){
int zz = que.front(); que.pop();
for(int i=;i<g[zz].size();i++){
int to = g[zz][i].first; in[to]--;
if(!in[to]) sz++,que.push(to);
dis[to] = max(dis[to],dis[zz]+g[zz][i].second);
}
}
if(sz != maxnum+) puts("-1");
else printf("%lld\n",dis[maxnum+]);
} void addedge(int from,int to,int w){
g[from].push_back(make_pair(to,w));
in[to]++;
} void ins(int now){
int np = ++num,p=lst; maxlen[np] = maxlen[lst]+;
st[len-now-] = np;
for(;p&&!nxt[p][str[now]-'a'];p = fa[p]) nxt[p][str[now]-'a'] = np;
if(!p) fa[np] = ;
else{
int q = nxt[p][str[now]-'a'];
if(maxlen[q] == maxlen[p]+) fa[np] = q;
else{
int nq = ++num; maxlen[nq] = maxlen[p]+;
for(int i=;i<;i++) nxt[nq][i] = nxt[q][i];
fa[nq] = fa[q];
fa[q] = nq; fa[np] = nq;
for(;p&&nxt[p][str[now]-'a']==q;p=fa[p])nxt[p][str[now]-'a']=nq;
}
}
lst = np;
} void findpos(int now,int dt,int pp){
if(chain[now].size() == ) return;
int l = ,r = chain[now].size()-;
while(l < r){
int mid = (l+r)/;
if(ra[chain[now][mid]]-la[chain[now][mid]]>=pp) r = mid;
else l = mid+;
}
l = chain[now][l];
if(ra[l]-la[l]<pp) return;
addedge(bh[dt],bh[l],ra[dt]-la[dt]+);
} int cmp(int alpha,int beta){
if(ra[alpha]-la[alpha] < ra[beta]-la[beta]) return ;
else return ;
} void read(){
scanf("%s",str);
len = strlen(str);
scanf("%d",&na);
for(int i=;i<=na;i++) scanf("%d%d",&la[i],&ra[i]);
for(int i=;i<=na;i++)la[i]=len-la[i],ra[i]=len-ra[i],swap(la[i],ra[i]);
scanf("%d",&nb);
for(int i=;i<=nb;i++) scanf("%d%d",&lb[i],&rb[i]);
for(int i=;i<=nb;i++)lb[i]=len-lb[i],rb[i]=len-rb[i],swap(lb[i],rb[i]);
for(int i=len-;i>=;i--) ins(i);
buildRMQ();
for(int i=;i<=num;i++){addedge(fa[i],i,);} for(int i=;i<=na;i++){
int ym = findhhh(st[ra[i]],ra[i]-la[i]);
chain[ym].push_back(i);
}
for(int i=;i<=num;i++) sort(chain[i].begin(),chain[i].end(),cmp);
maxnum = num;
for(int i=;i<=num;i++)
for(int j=;j<chain[i].size();j++) bh[chain[i][j]] = ++maxnum; for(int i=;i<=num;i++)
if(chain[i].size())addedge(fa[i],bh[chain[i][]],);
for(int i=;i<=num;i++){
for(int j=;j<(int)chain[i].size()-;j++)
addedge(bh[chain[i][j]],bh[chain[i][j+]],);
}
for(int i=;i<=na;i++) addedge(,bh[i],);
for(int i=;i<=na;i++) addedge(bh[i],maxnum+,ra[i]-la[i]+); for(int i=;i<=nb;i++){
int ym = findhhh(st[rb[i]],rb[i]-lb[i]);
lk[i] = ym;
}
scanf("%d",&m);
for(int i=;i<=m;i++){
int x,y; scanf("%d%d",&x,&y);
addedge(bh[x],lk[y],ra[x]-la[x]+);
findpos(lk[y],x,rb[y]-lb[y]);
}
} int main(){
//freopen("1.in","r",stdin);
int Tmp; scanf("%d",&Tmp);
while(Tmp--){
init();
read();
topu();
}
return ;
}

最新文章

  1. hdu 4920 Matrix multiplication bitset优化常数
  2. Windows Azure Virtual Machine (33) Azure虚拟机删除重建
  3. php浏览历史记录
  4. DWZ (JUI) 教程 navTab 刷新分析
  5. [玲珑OJ1044] Quailty and Binary Operation (FFT+cdq分治)
  6. EF框架step by step(8)—Code First DataAnnotations(2)
  7. 【CF】121 Div.1 C. Fools and Roads
  8. C 程序实现密码隐秘输入 linux系统可执行
  9. C++中 #include&lt;&gt;与#include&quot;&quot;
  10. python五十六课——正则表达式(常用函数之compile())
  11. MATLAB:图像裁切(imcrop函数)
  12. 企业级iptables防火墙实战
  13. CentOS6.4下邮件服务器搭建
  14. java8中ConcurrentHashMap
  15. Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点
  16. Linux命令 dmesg:分析内核产生的信息
  17. &#39;Microsoft.VisualStudio.Editor.Implementation.EditorPackage&#39; package did not load correctly
  18. ASP.NET MVC 手机短信验证
  19. MD5签名
  20. Linux下postgres安装fuzzystrmatch其他拓展包

热门文章

  1. Socket: Java Socket 几个重要的TCP/IP选项解析(转)
  2. win10: ctrl+shift不能切换输入法的问题
  3. idea 报错javax/xml/bind/DatatypeConverter
  4. windows10 环境下的RabbitMQ安装步骤(图文)
  5. idea中copyright使用
  6. 关于spring项目报错:找不到元素 &#39;beans&#39; 的声明的解决办法
  7. Form表单的传递与接收
  8. 容器版Jenkins官方镜像 本身自带了 Java
  9. 《第一本Docker书》学习笔记——第3章 Docker入门
  10. Win10安装DB2配置笔记