先考虑l=1,r=|s|的部分分,需要求出t每一个前缀的不是s子串的最长后缀,记作pp[k],有以下限制:
1.pp[pos[k]]<len(pos[k]表示k的某一个结束位置),因为不能被匹配
2.len[fa[k]]<len<=len[k],因为这个点上本来就只有这些串
由此得到答案为sigma(max(0,len[j]-max(len[fa[j]],pp[pos[j]])))(要对0取max)
维护出s从li到ri的后缀自动机,但好像不太容易。不妨换个角度,即要求其的right集合存在一个值在[li,ri]之间
也就是说在计算s的SAM同时,求出每一个节点的right集合
维护线段树,线段树下标表示位置,值表示是否是right集合。那么SAM上的父亲就是所有儿子right集合的并,也就是线段树合并
(注意:因为要保留参与合并的线段树,所以要新建节点)
同时线段树还能很方便的判断区间中有没有1,求区间和即可
但是要注意,此时不能直接跳fa,而是要一个一个减长度(因为可能无法匹配该节点最长串,但能匹配较短的串)

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 2000005
4 #define mid (l+r>>1)
5 struct ji{
6 int nex,to;
7 }edge[N];
8 int V,x,last,fa[N],pos[N],len[N],ch[N][26];
9 int VV,E,n,m,a,b,r[N],head[N],pp[N],ls[N*16],rs[N*16];
10 long long ans;
11 char s[N],t[N];
12 int New(){
13 fa[++V]=0;
14 len[V]=pos[V]=0;
15 memset(ch[V],0,sizeof(ch[V]));
16 return V;
17 }
18 void add_edge(int x,int y){
19 edge[E].nex=head[x];
20 edge[E].to=y;
21 head[x]=E++;
22 }
23 void add(int c,int id){
24 int p=last,np=last=New();
25 len[np]=len[p]+1;
26 pos[V]=id;
27 for(;(p)&&(!ch[p][c]);p=fa[p])ch[p][c]=np;
28 if (!p)fa[np]=x;
29 else{
30 int q=ch[p][c];
31 if (len[q]==len[p]+1)fa[np]=q;
32 else{
33 int nq=New();
34 pos[nq]=pos[q];
35 len[nq]=len[p]+1;
36 memcpy(ch[nq],ch[q],sizeof(ch[q]));
37 fa[nq]=fa[q];
38 fa[q]=fa[np]=nq;
39 for(;(p)&&(ch[p][c]==q);p=fa[p])ch[p][c]=nq;
40 }
41 }
42 }
43 void update(int &k,int l,int r,int x){
44 k=++VV;
45 if (l==r)return;
46 if (x<=mid)update(ls[k],l,mid,x);
47 else update(rs[k],mid+1,r,x);
48 }
49 int query(int k,int l,int r,int x,int y){
50 if ((!k)||(l>y)||(x>r))return 0;
51 if ((x<=l)&&(r<=y))return 1;
52 return query(ls[k],l,mid,x,y)|query(rs[k],mid+1,r,x,y);
53 }
54 void merge(int &k1,int k2){
55 if (k1*k2==0){
56 k1+=k2;
57 return;
58 }
59 ls[++VV]=ls[k1];
60 rs[VV]=rs[k1];
61 k1=VV;
62 merge(ls[k1],ls[k2]);
63 merge(rs[k1],rs[k2]);
64 }
65 void dfs(int k){
66 if (pos[k])update(r[k],1,n,pos[k]);
67 for(int i=head[k];i!=-1;i=edge[i].nex){
68 dfs(edge[i].to);
69 merge(r[k],r[edge[i].to]);
70 }
71 }
72 int main(){
73 scanf("%s%d",s,&m);
74 len[0]=-1;
75 n=strlen(s);
76 x=last=New();
77 for(int i=0;s[i];i++)add(s[i]-'a',i+1);
78 memset(head,-1,sizeof(head));
79 for(int i=2;i<=V;i++)add_edge(fa[i],i);
80 dfs(1);
81 x=New();
82 for(int i=1;i<=m;i++){
83 scanf("%s%d%d",t,&a,&b);
84 V=x-1;
85 last=New();
86 for(int j=0,k=1,l=0;t[j];pp[j++]=++l){
87 int c=t[j]-'a';
88 add(c,j);
89 while (!query(r[ch[k][c]],1,n,a+l,b)){
90 if (--l<0)break;
91 if (l==len[fa[k]])k=fa[k];
92 }
93 if (l<0)k=1;
94 else k=ch[k][c];
95 }
96 ans=0;
97 for(int j=x;j<=V;j++)ans+=max(0,len[j]-max(len[fa[j]],pp[pos[j]]));
98 printf("%lld\n",ans);
99 }
100 }

[bzoj5417]你的名字的更多相关文章

  1. 【BZOJ5417】[NOI2018]你的名字(线段树,后缀自动机)

    [BZOJ5417][NOI2018]你的名字(线段树,后缀自动机) 题面 BZOJ 洛谷 题解 首先考虑\(l=1,r=|S|\)的做法,对于每次询问的\(T\)串,暴力在\(S\)串的\(SAM\ ...

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

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

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

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

  4. [BZOJ5417] [NOI2018]你的名字

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

  5. Material Design Reveal effect(揭示效果) 你可能见过但是叫不出名字的小效果

    Material Design Reveal effect(揭示效果) 你可能见过但是叫不出名字的小效果 前言: 每次写之前都会来一段(废)话.{心塞...} Google Play首页两个tab背景 ...

  6. idea怎么设置自己的名字和时间

    1.直接修改idea64.exe.vmoptions 里面添加上 -Duser.name=yourname 重启即可生效 1.file - settings-Editor- File and Code ...

  7. Java名字的由来

    Java语言的历程丰富多彩,被现在众多程序员和企业广泛使用,不用质疑这是Java的领先技术的结果. Java是Sun公司开发的一种编程语言,Sun公司最初的方向是让Java来开发一些电器装置程序,如: ...

  8. iOS获取app图标和启动图片名字(AppIcon and LaunchImage's name)

    在某种场景下,可能我们需要获取app的图标名称和启动图片的名称.比如说app在前台时,收到了远程通知但是通知栏是不会有通知提醒的,这时我想做个模拟通知提示,需要用到icon名称:再比如在加载某个控制器 ...

  9. 【Centos】修改网卡名字&随之出现的问题

    自从学了工具tcpdump之后,里面会需要涉及到针对某个网卡抓包,因而会输入网卡名字,可是centOS7蛋疼的网卡默认命名实在是让人心碎,所以就想到了要修改网卡名字,步骤如下:(以下步骤涉及到我的错误 ...

随机推荐

  1. 洛谷 P1862 输油管道问题

    题意 题目链接:P1862 输油管道问题 不难看出每个油井的 \(x\) 坐标是没用的,所以问题转化为如下. 代数意义:给出 \(n\) 个数 \(y_1,y_2,\ldots,y_n\),找一个数 ...

  2. sql提示1055 不让你group by

    是不是突然写好的sql语句 部署上去就 Expression #2 of SELECT list is not in GROUP BY clause and containsnonaggregated ...

  3. NOI 2017 Day1 题解

    被虐爆了... T1 整数 题目传送门 Description 有一个整数 \(x\),有 \(n\) 此操作,每次操作为以下两种情况: 给出 \(a,b\),将 \(x\) 加上 \(a\times ...

  4. 题解 Christmas Game

    题目传送门 题目大意 给出 \(t\) 个 \(n\) 个点 \(m\) 条边的无向图,每次可以从任意一棵树选择一条边删掉,然后该树不与根(为 \(1\) )联通的部分被删掉.不能操作的人输.问谁有必 ...

  5. 洛谷2120 [ZJOI2007]仓库建设(斜率优化dp)

    感觉和锯木厂那个题很类似的. 其实这个题还那个题唯一的区别就是\(dp\)转移式子中的\(f\)变成了\(g\) qwq不想多说了 直接看我的前一篇题解吧qwq #include<iostrea ...

  6. 洛谷3195 [HNOI2008]玩具装箱TOY(斜率优化+dp)

    qwq斜率优化好题 第一步还是考虑最朴素的\(dp\) \[dp=dp[j]+(i-j-1+sum[i]-sum[j])^2 \] 设\(f[i]=sum[i]+i\) 那么考虑将上述柿子变成$$dp ...

  7. 2020.10.9--vj个人赛补题

    B - A Tide of Riverscape 题意:给出一组字符串,由'0','1',' . '组成,' . '可以换成 0或1,判断第 i  个和第 i+p 个字符是否可以不相等,如果可以则输出 ...

  8. 欧姆龙PLC HostLink协议整理

    欧姆龙PLC HostLink协议整理 1.常用的存储器功能区 CIO: 输入继电器  272 点(17 CH) 0.00-16.15 输出继电器  272 点(17 CH) 100.00-116.1 ...

  9. [对对子队]会议记录5.22(Scrum Meeting9)

    今天已完成的工作 梁河览 ​ 工作内容:修改第一到九关新手引导,修复关卡选择bug ​ 相关issue:优化初步导出版本 ​ 相关签入:fix:修改第一关到第九关的新手引导和地图场景的bug 马嘉 ​ ...

  10. the Agiles Scrum Meeting 2

    会议时间:2020.4.10 21:00 1.每个人的工作 今天已完成的工作 yjy:debug:班级创建了个人项目不能访问班级:教师窗口的前端bug. issues:Bug:教师创建博客时显示项目为 ...