看到题目名字去补番是种怎么样的体验

我只会 \(68\) 分,打了个暴力。正解看了一会儿,发现跟 \([HEOI2016/TJOI2016]\) 字符串很像,用线段树合并维护 \(endpos\) 集合,然后一边匹配一边记录答案。

\[ans=\sum_{i=1}^{cnt}max(0,len_i-max(len_{fa_i},lim_{pos_i}))
\]

\(Code\ Below:\)

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1000000+10;
int n,m,q,a[maxn],b[maxn],rt[maxn],L[maxn*40],R[maxn*40],sum[maxn*40],tot;
char s[maxn]; struct SAM{
int last,cnt,ch[maxn][26],fa[maxn],l[maxn],pos[maxn],lim[maxn];
void init(){
for(int i=1;i<=cnt;i++){
for(int j=0;j<26;j++) ch[i][j]=0;
}
last=cnt=1;
}
void insert(int c,int id){
int p=last,q=++cnt;last=q;l[q]=l[p]+1;pos[q]=id;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=q;
if(!p) fa[q]=1;
else {
int r=ch[p][c];
if(l[p]+1==l[r]) fa[q]=r;
else {
int s=++cnt;l[s]=l[p]+1;pos[s]=pos[r];
memcpy(ch[s],ch[r],sizeof(ch[r]));
fa[s]=fa[r];fa[r]=fa[q]=s;
for(;p&&ch[p][c]==r;p=fa[p]) ch[p][c]=s;
}
}
}
ll calc(){
ll ans=0;
for(int i=2;i<=cnt;i++) ans+=max(0,l[i]-max(l[fa[i]],lim[pos[i]]));
return ans;
}
}S,T; void update(int &now,int l,int r,int x){
if(!now) now=++tot;
sum[now]++;
if(l == r) return ;
int mid=(l+r)>>1;
if(x <= mid) update(L[now],l,mid,x);
else update(R[now],mid+1,r,x);
} int merge(int x,int y){
if(x==0||y==0) return x+y;
int z=++tot;
sum[z]=sum[x]+sum[y];
L[z]=merge(L[x],L[y]);
R[z]=merge(R[x],R[y]);
return z;
} int query(int now,int Le,int Ri,int l,int r){
if(!now||Le>Ri) return 0;
if(Le <= l && r <= Ri) return sum[now];
int mid=(l+r)>>1,ans=0;
if(Le <= mid) ans+=query(L[now],Le,Ri,l,mid);
if(Ri > mid) ans+=query(R[now],Le,Ri,mid+1,r);
return ans;
} int main()
{
scanf("%s",s+1);n=strlen(s+1);S.init();
for(int i=1;i<=n;i++){
S.insert(s[i]-'a',i);
update(rt[S.last],1,n,i);
}
for(int i=1;i<=S.cnt;i++) b[S.l[i]]++;
for(int i=1;i<=S.cnt;i++) b[i]+=b[i-1];
for(int i=S.cnt;i>=1;i--) a[b[S.l[i]]--]=i;
for(int i=S.cnt;i>=2;i--) rt[S.fa[a[i]]]=merge(rt[S.fa[a[i]]],rt[a[i]]);
scanf("%d",&q);
int l,r,p,c,len;
while(q--){
scanf("%s%d%d",s+1,&l,&r);m=strlen(s+1);
T.init();len=0;p=1;
for(int i=1;i<=m;i++){
c=s[i]-'a';T.insert(c,i);
while(1){
if(S.ch[p][c]&&query(rt[S.ch[p][c]],l+len,r,1,n)){
len++;p=S.ch[p][c];
break;
}
if(len==0) break;
if(--len==S.l[S.fa[p]]) p=S.fa[p];
}
T.lim[i]=len;
}
printf("%lld\n",T.calc());
}
return 0;
}

[NOI2018]你的名字(后缀自动机+线段树合并)的更多相关文章

  1. bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并)

    bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并) bzoj Luogu 给出一个字符串 $ S $ 及 $ q $ 次询问,每次询问一个字符串 $ T $ ...

  2. BZOJ5417[Noi2018]你的名字——后缀自动机+线段树合并

    题目链接: [Noi2018]你的名字 题目大意:给出一个字符串$S$及$q$次询问,每次询问一个字符串$T$有多少本质不同的子串不是$S[l,r]$的子串($S[l,r]$表示$S$串的第$l$个字 ...

  3. BZOJ.5417.[NOI2018]你的名字(后缀自动机 线段树合并)

    LOJ 洛谷 BZOJ 考虑\(l=1,r=|S|\)的情况: 对\(S\)串建SAM,\(T\)在上面匹配,可以得到每个位置\(i\)的后缀的最长匹配长度\(mx[i]\). 因为要去重,对\(T\ ...

  4. luogu4770 [NOI2018]你的名字 后缀自动机 + 线段树合并

    其实很水的一道题吧.... 题意是:每次给定一个串\(T\)以及\(l, r\),询问有多少个字符串\(s\)满足,\(s\)是\(T\)的子串,但不是\(S[l .. r]\)的子串 统计\(T\) ...

  5. NOI 2018 你的名字 (后缀自动机+线段树合并)

    题目大意:略 令$ION2017=S,ION2018=T$ 对$S$建$SAM$,每次都把$T$放进去跑,求出结尾是i的前缀串,能匹配上$S$的最长后缀长度为$f_{i}$ 由于$T$必须在$[l,r ...

  6. [NOI2018]你的名字(后缀自动机+线段树)

    题目描述 小A 被选为了ION2018 的出题人,他精心准备了一道质量十分高的题目,且已经把除了题目命名以外的工作都做好了. 由于ION 已经举办了很多届,所以在题目命名上也是有规定的,ION 命题手 ...

  7. BZOJ3413: 匹配(后缀自动机 线段树合并)

    题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直 ...

  8. cf666E. Forensic Examination(广义后缀自动机 线段树合并)

    题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并 首先对所有的\(t_i\)建个广义后缀自动机,这样可以得到所有子串信息. 考虑把询问离线,然后把\(S\)拿到自动机上跑,同时维护一下 ...

  9. [Luogu5161]WD与数列(后缀数组/后缀自动机+线段树合并)

    https://blog.csdn.net/WAautomaton/article/details/85057257 解法一:后缀数组 显然将原数组差分后答案就是所有不相交不相邻重复子串个数+n*(n ...

  10. 模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)

    模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合) Code: #include <bits/stdc++.h> using namespace std; #define ...

随机推荐

  1. mybatis缓存(一,二级别)

    数据查找过程: 二级缓存(默认关闭) -> 一级缓存(默认开启) -> 数据库 一级缓存: 一级缓存是SqlSession自带的.SqlSession对象被创建,一级缓存就存在了.//是针 ...

  2. 【Java】JABX实现对象与XML互转

    JABX简介 JAXB能够使用Jackson对JAXB注解的支持实现(jackson-module-jaxb-annotations),既方便生成XML,也方便生成JSON,这样一来可以更好的标志可以 ...

  3. Ajax的爬取心得

    一.查找到js的网址 在我们做爬虫的时候,如何判断一个数据是Ajax(asynchronous JavaScript And Xml,异步的JavaScript和Xml), 首先是数据的加载,在请求网 ...

  4. 【转】Centos7下Yum安装PHP5.5,5.6,7.0

    默认的版本太低了,手动安装有一些麻烦,想采用Yum安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包,先删除他们 ...

  5. hadoop 修改datanode balance带宽使用限制

    前段时间,一个客户现场的Hadoop看起来很不正常,有的机器的存储占用达到95%,有的机器只有40%左右,刚好前任的负责人走了,这边还没有明确接班人的时候. 我负责的大数据计算部分,又要依赖Hadoo ...

  6. idea中使用thymeleaf标签时有红色的波浪线怎么去掉

    使用最新版本的idea2017可以解决,方法如下: 选择File->Settings->Editor->Inspections,然后搜索thymeleaf 将Expression v ...

  7. 2019.01.21 NOIP训练 ak树(点分治)

    传送门 题意简述:给一棵带权树,问在上面随机选两个点距离是4的倍数的概率. 思路: 由于总方案数为定值n2n^2n2,所以只用求总方案数. 这个跟聪聪可可差不多,可以用类似树形dpdpdp的方法边点分 ...

  8. 2019.01.09 bzoj3697: 采药人的路径(点分治)

    传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...

  9. ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树,倍增lca)

    https://nanti.jisuanke.com/t/31462 要求在一个矩形中任意选两个点都有唯一的通路,所以不会建多余的墙. 要求满足上述情况下,建墙的费用最小.理解题意后容易想到首先假设全 ...

  10. ubuntu 16.04 安装pgadmin3

    1.Ctrl+Alt+t 打开终端 2.输入 wget -q -O - http://www.pgadmin.org/pgp/archive_key_debian_Ubuntu.gpg | sudo ...