题目分析:

建出后缀自动机,然后把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. 修改layui的表单手机、邮箱验证可以为空怎么实现?

      修改layui的表单手机.邮箱验证可以为空   解决办法: 修改源码: 把表单验证源代码(form.js)的正则表达式改一下,例如手机的正则为:/^1d{10}$/,可以改成/^$|^1d{10} ...

  2. springIoC注解

    一.通过注解注入Bean @Component:组件(spring扫描包下有该注解的类) @ComponentScan(包名):组件扫描(spring扫描该包名下的类) @Configuration: ...

  3. ActiveMQ持久化

    ActiveMQ中,持久化是值对消息数据的持久化.在ActiveMQ中,默认的消息是保存在内存中的.当内存容量不足的时候,或ActiveMQ正常关闭的时候,会将内存中的未处理的消息持久化到磁盘中.具体 ...

  4. svn: E205007: None of the environment variables SVN_EDITOR

    svn propedit svn:ignore .svn: E205007: None of the environment variables SVN_EDITOR, VISUAL or EDITO ...

  5. Scala里面的排序函数的使用

    排序方法在实际的应用场景中非常常见,Scala里面有三种排序方法,分别是: sorted,sortBy ,sortWith 分别介绍下他们的功能: (1)sorted 对一个集合进行自然排序,通过传递 ...

  6. visual studio code利用自身携带debug调试

    在.vscode文件夹下,添加如下文件 1) launch.json 内容如下 { "version": "0.2.0", "configuratio ...

  7. scons 简单入门

    scons 简单入门 摘自:https://www.jianshu.com/p/e4bd3ab9e5d6 0.2042019.01.20 12:58:44字数 1201阅读 3021 简单入门 hel ...

  8. 搭建Keepalived+LVS-DR集群

    (1).Keepalived概述 keepalived 是一个类似于 layer3, 4 & 5 交换机制的软件,也就是我们平时说的第 3 层.第 4 层和第 5层交换. Keepalived ...

  9. 打乱数组 shuffle

    <?php $arr = range(,); print_r($arr); echo '<br />'; shuffle($arr); print_r($arr); ?> Ar ...

  10. [Log4j使用教程] JavaSE/JavaEE/SpringMVC中使用Log4j

    要想使用Log4j, 首先需要下载到Log4j的jar, Download: http://www.apache.org/dyn/closer.cgi/logging/log4j/1.2.17/log ...