题目分析:

建出后缀自动机,然后把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 ;
}

LOJ3049 [十二省联考2019] 字符串问题 【后缀自动机】【倍增】【拓扑排序】的更多相关文章

  1. [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增

    题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...

  2. 洛谷.5284.[十二省联考2019]字符串问题(后缀自动机 拓扑 DP)

    LOJ BZOJ 洛谷 对这题无话可说,确实比较...裸... 像dls说的拿拓扑和parent树一套就能出出来了... 另外表示BZOJ Rank1 tql... 暴力的话,由每个\(A_i\)向它 ...

  3. [LOJ3049] [十二省联考 2019] 字符串问题

    题目链接 LOJ:https://loj.ac/problem/3049 洛谷:https://www.luogu.org/problemnew/show/P5284 BZOJ:https://www ...

  4. 洛谷P5284 [十二省联考2019]字符串问题 [后缀树]

    传送门 思路 设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度. 然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建 ...

  5. 洛谷P5284 [十二省联考2019]字符串问题(SAM+倍增+最长路)

    题面 传送门 题解 首先,我们把串反过来,那么前缀就变成后缀,建一个\(SAM\).我们发现一个节点的后缀是它的所有祖先 那么我们是不是直接按着\(parent\)树建边就可以了呢? 显然不是.我们假 ...

  6. 【BZOJ5496】[十二省联考2019]字符串问题(后缀树)

    [BZOJ5496][十二省联考2019]字符串问题(后缀树) 题面 BZOJ 洛谷 题解 首先显然可以把具有支配关系的串从\(A\)到\(B\)连一条有向边,如果\(B_i\)是\(A_j\)的前缀 ...

  7. Luogu P5284 [十二省联考2019]字符串问题

    好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...

  8. P5284 [十二省联考2019]字符串问题

    这是一道涵盖了字符串.图论.数据结构三个方面的综合大题. 把这道题放在D1T2的人应该拖出去打 前置芝士 首先,您至少要会topsort. 其次,如果您只想拿个暴力分,字符串Hash就足够了:如果您想 ...

  9. 【题解】Luogu P5284 [十二省联考2019]字符串问题

    原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长 ...

随机推荐

  1. mysql的备份与还原,安装(window)

    之前一直使用的navicat的自动的备份功能.但是在使用navicat的还原功能时,贼慢. 今天要做的是window服务器上将mysql单个数据库备份.然后还原到我的mac笔记本上. 本来以为很快的, ...

  2. Opencv加载网络图片

    opencv加载网络图片 #include <iostream> #include <opencv2/opencv.hpp> using namespace std; usin ...

  3. Spring cloud微服务安全实战-6-4权限控制改造

    授权,权限的控制 令牌里的scope包含fly就有权限访问.根据Oauth的scope来做权限控制, 要让@PreAuthorize生效,就要在启动类里面写一个注解. 里面有一个属性叫做,就是在方法的 ...

  4. django项目mysite

    项目建立 建立项目mysite 各文件和目录解释: 外层的mysite/目录与Django无关,只是你项目的容器,可以任意重命名. manage.py:一个命令行工具,用于与Django进行不同方式的 ...

  5. django 中单独执行py文件修改用户名

    Python文件代码 import os import django # 在environ字典里设置默认Django环境,'xxxx.settings'指Django项目的配置文件 os.enviro ...

  6. Python - Django - ORM 自定义表名

    通过 Django 建立的表 命名方式为:项目名_表名 可以将该默认命名方式进行修改 models.py: from django.db import models class Person(mode ...

  7. 看看该死的jquery.form.js的用法,不是个东西

    $("#btnReg").click(function () { var options = { //target: '#output', // 把服务器返回的内容放入id为out ...

  8. __proto__和prototype的一些理解

    var Person = function(name) { this.name = name; } var p = new Person(); new操作符的操作是 var p = {} p.__pr ...

  9. Linux下Mongodb安装和启动配置 转载

    原文地址:https://www.cnblogs.com/Jimmy104/p/6181899.html 以下文章为转载,感谢网友,原文链接 http://blog.csdn.net/yuwenrul ...

  10. stochastic noise and deterministic noise

    在机器学习中,导致overfitting的原因之一是noise,这个noise可以分为两种,即stochastic noise,随机噪声来自数据产生过程,比如测量误差等,和deterministic ...