后缀自动机+二分+倍增+线段树合并

后缀自动机真好用

后面一个串是固定的,那么我们要对前面的串进行一些操作。我们想既然是求lcp,那么我们得先翻转原串,这样前缀变成了后缀,然后二分一下,从d在自动机上的位置向上倍增,走到第一个Max大于当前答案的位置,用线段树合并判断一下当前是否满足。还是很好写的,具体看代码。注意线段树合并必须新开一个节点。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + ;
int n, m;
int fa[N][], mp[N << ];
vector<int> G[N];
namespace Segment_Tree
{
int cnt;
int root[N], sum[N * ], lc[N * ], rc[N * ];
void update(int &x, int l, int r, int p, int d)
{
x = ++cnt;
sum[x] += d;
if(l == r) return;
int mid = (l + r) >> ;
if(p <= mid) update(lc[x], l, mid, p, d);
else update(rc[x], mid + , r, p, d);
}
int merge(int u, int v)
{
if(!u) return v;
if(!v) return u;
int w = ++cnt;
sum[w] = sum[u] + sum[v];
lc[w] = merge(lc[u], lc[v]);
rc[w] = merge(rc[u], rc[v]);
return w;
}
int query(int x, int l, int r, int a, int b)
{
if(!x || l > b || r < a) return ;
if(l >= a && r <= b) return sum[x];
int mid = (l + r) >> ;
return (query(lc[x], l, mid, a, b) + query(rc[x], mid + , r, a, b));
}
} using namespace Segment_Tree;
namespace SAM
{
struct node {
int val, par;
int ch[];
} t[N];
int sz = , Root = , last = ;
int nw(int x)
{
t[++sz].val = x;
return sz;
}
void extend(int c)
{
int p = last, np = nw(t[p].val + );
while(p && !t[p].ch[c]) t[p].ch[c] = np, p = t[p].par;
if(!p) t[np].par = Root;
else
{
int q = t[p].ch[c];
if(t[q].val == t[p].val + ) t[np].par = q;
else
{
int nq = nw(t[p].val + );
memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));
t[nq].par = t[q].par;
t[q].par = t[np].par = nq;
while(p && t[p].ch[c] == q) t[p].ch[c] = nq, p = t[p].par;
}
}
last = np;
mp[t[np].val] = np;
update(root[np], , n, t[np].val, );
}
void dfs(int u)
{
for(int i = ; i < G[u].size(); ++i)
{
int v = G[u][i];
fa[v][] = u;
dfs(v);
root[u] = merge(root[u], root[v]);
}
}
} using namespace SAM;
char s[N];
bool check(int len, int l, int r, int u)
{
for(int i = ; i >= ; --i)
if(t[fa[u][i]].val >= len)
u = fa[u][i];
// if(t[u].val < len) return 0;
return query(root[u], , n, l + len - , r);
}
int main()
{
// freopen("heoi2016_str.in", "r", stdin);
// freopen("heoi2016_str.out", "w", stdout);
scanf("%d%d%s", &n, &m, s + );
reverse(s + , s + n + );
for(int i = ; i <= n; ++i) extend(s[i] - 'a');
for(int i = ; i <= sz; ++i) G[t[i].par].push_back(i);
dfs(Root);
for(int j = ; j <= ; ++j)
for(int i = ; i <= sz; ++i)
fa[i][j] = fa[fa[i][j - ]][j - ];
while(m--)
{
int a, b, c, d, ta, tb, tc, td;
scanf("%d%d%d%d", &ta, &tb, &tc, &td);
a = n - tb + ;
b = n - ta + ;
c = n - td + ;
d = n - tc + ;
int l = , r = min(b - a + , d - c + ), ans = ;
while(r - l > )
{
int mid = (l + r) >> ;
if(check(mid, a, b, mp[d])) l = ans = mid;
else r = mid;
}
printf("%d\n", ans);
}
// fclose(stdin);
// fclose(stdout);
return ;
}

bzoj4556的更多相关文章

  1. 【BZOJ4556】字符串(后缀数组,主席树)

    [BZOJ4556]字符串(后缀数组,主席树) 题面 BZOJ 题解 注意看题: 要求的是\([a,b]\)的子串和[c,d]的\(lcp\)的最大值 先来一下暴力吧 求出\(SA\)之后 暴力枚举\ ...

  2. BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...

  3. 【BZOJ4556】[Tjoi2016&Heoi2016]字符串 后缀数组+二分+主席树+RMQ

    [BZOJ4556][Tjoi2016&Heoi2016]字符串 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一 ...

  4. [BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1360  Solved: 545[S ...

  5. BZOJ4556: [Tjoi2016&Heoi2016]字符串

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开 ...

  6. Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 169  Solved: 87[Sub ...

  7. 2019.02.27 bzoj4556: [Tjoi2016&Heoi2016]字符串(二分答案+sam+线段树合并)

    传送门 题意:给一个字符串SSS. 有mmm次询问,每次给四个参数a,b,c,da,b,c,da,b,c,d,问s[a...b]s[a...b]s[a...b]的所有子串和s[x...y]s[x... ...

  8. bzoj4556(sam)

    二分答案,(具体可见http://blog.csdn.net/neither_nor/article/details/51669114),然后就是判定问题,sa和sam都可以做,用sam写了一下,先用 ...

  9. BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱 ...

  10. BZOJ4556 HEOI2016字符串

    没错,又是这题,使用后缀自动机,反向建树,主席树维护right集合. By:大奕哥 #include<bits/stdc++.h> using namespace std; ; ]; ch ...

随机推荐

  1. SQL视图优化改写为存储过程遇到 双引号 单引号问题

    核心在于拼接SQL字符串中遇到中文双引号问题:   可以使用系统函数 替换掉set @pageStr =   replace(@queryStr,'"','''')  不过更推荐 使用两个单 ...

  2. linux的主分区与逻辑分区的关系

     主分区和扩展分区的差别在于主分区位于硬盘的最開始.MBR 扇区的位置.这个位置的数据在计算机启动时.会自己主动被 BIOS 读取而且运行,也就是说这个位置的分区表会自己主动被 BIOS 读取到内 ...

  3. LOCAL_CFLAGS参数说明

    1.-Wall 是打开警告开关 2.-O 代表默认优化,可选:-O0不优化,-O1低级优化,-O2中级优化,-O3高级优化,-Os代码空间优化 3.-g 是生成调试信息,生成的可执行文件具有和源代码关 ...

  4. sql之浅谈视图的作用

    [数据库]☆★sql之浅谈视图的作用 在一个项目的实际开发过程中牵涉到复杂业务的时候,我们不可避免的须要使用中间表来进行数据连接,有的同学就说了,我能够採用Hibernate进行主外键进行关联啊?多对 ...

  5. UML类间关系

    1继承 指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系:在Java中此类关系通过关键字exten ...

  6. 【转载】.NET Remoting学习笔记(三)信道

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:♂风车车.Net .NET Framework ...

  7. oracle SQL语句(转)

    Oracle数据库语句大全 ORACLE支持五种类型的完整性约束 NOT NULL (非空)--防止NULL值进入指定的列,在单列基础上定义,默认情况下,ORACLE允许在任何列中有NULL值. CH ...

  8. HDU 5371 Hotaru&#39;s problem(Manacher算法+贪心)

    manacher算法详见 http://blog.csdn.net/u014664226/article/details/47428293 题意:给一个序列,让求其最大子序列,这个子序列由三段组成, ...

  9. 用python编写的简易端口扫描器

    #coding = utf-8 ''' python 3.4 通过简单的TCP端口连接来判断指定IP是否开放了指定端口. ''' import socket import optparse impor ...

  10. Centos修改静态IP

    vim /etc/sysconfig/network-scripts/ifcfg-eth0代开配置文件 写入 DEVICE=eth0 #描述网卡对应的设备别名,例如ifcfg-eth0的文件中它为et ...