题目分析:

建出后缀自动机,然后把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. 《Linux设备驱动程序》编译LDD3的scull驱动问题总结***

    由于Linux内核版本更新的原因,LDD3(v2.6.10)提供的源码无法直接使用,下面是本人编译scull源码时出现的一些问题及解决方法.编译环境:Ubuntu 10.04 LTS(kernel v ...

  2. 宝塔php open_basedir restriction in effect

    解决方法一: 1.网站管理的  防跨站攻击去掉勾选,重启网站,清除浏览器缓存 解决方法二:

  3. [Java.File]如果写 File filesFolder = new File("/") ,在windows系统中,filesFolder 会去找哪个盘符? 答案:程序运行路径的根盘符.

    首先这段代码在Unix/Linux系统上会去找根路径,但在Windows系统上会去找C:盘还是D:盘还是其它盘呢? 其实它会去找user.dir所在盘符的根目录,user.dir即用户的当前工作目录, ...

  4. 【idea】idea远程调试代码

    一.前置条件 1.idea的代码和远程服务器代码保持一致 二.远程服务器配置 服务启动时,需要给jvm添加指定参数,进行启动 -agentlib:jdwp=transport=dt_socket,se ...

  5. linux记录-安装elk记录(参考博文)

    什么是ELK? 通俗来讲,ELK是由Elasticsearch.Logstash.Kibana .filebeat三个开源软件的组成的一个组合体,这三个软件当中,每个软件用于完成不同的功能,ELK 又 ...

  6. Python - Django - 上传文件

    upload.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  7. Go micro 开发微服务步骤

    1.写 proto文件,定义接口和服务 2.实现 接口,注册 handle 3.调用服务:直接用rpc 客户端调用,或者用 api http web等调用 api http web 等服务可以对客户端 ...

  8. 修改ecshop的70种技巧

    1.如何修改网站”欢迎惠临本店”答复(dafu):languages\zh_cn\common.php文件中,$_LANG['welcome']=’欢迎惠临本店’:将他修改成你需要的字样. 2.如何修 ...

  9. 16、vue引入echarts,划中国地图

    vue引入echarts npm install echarts --save main.js引入 import echarts from 'echarts' Vue.prototype.$echar ...

  10. 机器学习之径向基神经网络(RBF NN)

    本文基于台大机器学习技法系列课程进行的笔记总结. 主要内容如下图所示: 首先介绍一下径向基函数网络的Hypothesis和网络的结构,然后介绍径向基神经网络学习算法,以及利用K-means进行的学习, ...