传送门

upd 19.4.24:

WC这个做法真的有问题,不往回跳会WA是因为一开始跳到了S[1...l-1]所对应的点,然后往后接字符的时候可能会因为不在正确的endpos中,然后往回跳过头,其实一开始只要从起点开始跳就行了

Orz @Itst ddw


这题写死我了,因为一点点鬼会注意到的细节调好久,,,

先考虑前17个点,如果我们不考虑T的不同子串限制,那么就是把T放在S的SAM上匹配,答案为\(\sum_{i=1}^{|T|}i-l[i]\)(匹配长度).考虑怎么判重,对T也构建一个SAM,由于每个前缀的贡献答案的子串左端点在\([1,i-l[i])\)之间,对应到parent树上就是若干条链,那么每个位置的贡献就是对应链的没有被前面的链覆盖的部分

后面的点,首先我们每次要跳到S[1...l-1]所对应的点,然后把T放在上面匹配,不过可能匹配过程中,S匹配上的子串没有在[l,r]之间的,这时候我们要跳parent,去掉匹配子串的前面一些部分,使得[l,r]之间出现对应的串.这个可以通过SAM每个节点开一棵线段树维护endpos集合,通过线段树合并维护,每次查询对应状态[l,r]中最大的结束位置-匹配长度+1是否\(\ge l\)

(这种做法有点问题,可能跳parent会因为串的前面部分而跳过头,导致匹配长度变小,从而导致答案变大,所以跳完后要尝试往回跳orz)

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double using namespace std;
const int N=1000000+10;
il LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
char cc[N],ss[N];
int n,m;
int an[N>>1],bk[N>>1],aa[N],loc[N>>1],st[N],tp;
int s[N*22],ch[N*22][2],rt[N],tot;
il void inst(int o1,int o2,int x)
{
int l=1,r=n;
s[o1]=max(s[o2],x);
while(l<r)
{
int mid=(l+r)>>1;
if(x<=mid)
{
ch[o1][0]=++tot,ch[o1][1]=ch[o2][1];
o1=ch[o1][0],o2=ch[o2][0];
r=mid;
}
else
{
ch[o1][0]=ch[o2][0],ch[o1][1]=++tot;
o1=ch[o1][1],o2=ch[o2][1];
l=mid+1;
}
s[o1]=max(s[o2],x);
}
}
int merge(int o1,int o2)
{
if(!o1||!o2) return o1+o2;
//if(o1==o2) return o1;
int o=++tot;
s[o]=max(s[o1],s[o2]);
ch[o][0]=merge(ch[o1][0],ch[o2][0]),ch[o][1]=merge(ch[o1][1],ch[o2][1]);
return o;
}
int quer(int o,int l,int r,int ll,int rr)
{
if(!o) return s[0];
if(ll<=l&&r<=rr) return s[o];
int mid=(l+r)>>1,an=s[0];
if(ll<=mid) an=/*max(an,*/quer(ch[o][0],l,mid,ll,rr)/*)*/;
if(rr>mid) an=max(an,quer(ch[o][1],mid+1,r,ll,rr));
return an;
}
struct SAM
{
int fa[N],len[N],a[N],la,tt;
int ch[N][26];
bool v[N];
SAM(){la=tt=1;}
il void inst(char c,int id)
{
int np=++tt,p=la;
la=np,a[np]=id,len[np]=len[p]+1;
while(p&&!ch[p][c-'a']) ch[p][c-'a']=np,p=fa[p];
if(!p) fa[np]=1;
else
{
int q=ch[p][c-'a'];
if(len[q]==len[p]+1) fa[np]=q;
else
{
int nq=++tt;
fa[nq]=fa[q],len[nq]=len[p]+1,fa[q]=fa[np]=nq;
for(int i=0;i<26;++i) ch[nq][i]=ch[q][i];
while(p&&ch[p][c-'a']==q) ch[p][c-'a']=nq,p=fa[p];
}
}
}
il void clear()
{
memset(ch,0,4*26*(tt+2));
memset(v,0,1*(tt+2));
memset(fa,0,4*(tt+2));
memset(len,0,4*(tt+2));
la=tt=1;
}
}a,b; int main()
{
scanf("%s",ss+1);
n=strlen(ss+1);
for(int i=1;i<=n;++i) a.inst(ss[i],i);
for(int i=1;i<=a.tt;++i) ++bk[a.len[i]];
for(int i=1;i<=n;++i) bk[i]+=bk[i-1];
for(int i=1;i<=a.tt;++i) aa[bk[a.len[i]]--]=i;
memset(s,-63,sizeof(s));
for(int i=a.tt,las;i;--i)
{
if(a.a[aa[i]]) las=rt[aa[i]],inst(rt[aa[i]]=++tot,las,a.a[aa[i]]);
rt[a.fa[aa[i]]]=merge(rt[a.fa[aa[i]]],rt[aa[i]]);
}
loc[0]=1;
for(int i=1,nw=1;i<=n;++i) loc[i]=nw=a.ch[nw][ss[i]-'a'];
int q=rd();
while(q--)
{
scanf("%s",cc+1);
m=strlen(cc+1);
LL ans=0;
int l=rd(),r=rd();
for(int i=1,nw=loc[l-1],kk=0;i<=m;++i)
{
int w=cc[i]-'a';
while(nw&&!a.ch[nw][w]) nw=a.fa[nw],kk=a.len[nw];
if(!nw) nw=1,kk=0;
else nw=a.ch[nw][w],++kk;
tp=0;
while(nw&&quer(rt[nw],1,n,l,r)-kk+1<l)
st[++tp]=nw,nw=a.fa[nw],kk=a.len[nw];
if(tp)
{
while(quer(rt[nw],1,n,l,r)-kk+1>=l) ++kk,nw=(kk<=a.len[nw])?nw:st[tp--];
--kk,nw=(kk>a.len[a.fa[nw]])?nw:a.fa[nw];
}
an[i]=kk;
}
b.clear();
for(int i=1;i<=m;++i) b.inst(cc[i],0);
b.v[0]=1;
for(int i=1,nw=1;i<=m;++i)
{
int w=cc[i]-'a',p=nw=b.ch[nw][w];
while(!b.v[p]&&b.len[p]>=an[i]) ans+=b.len[p]-max(b.len[b.fa[p]],an[i]),b.v[p]=1,p=b.fa[p];
}
printf("%lld\n",ans);
}
return 0;
}

luogu P4770 [NOI2018]你的名字的更多相关文章

  1. UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)

    NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...

  2. #P4770 [NOI2018]你的名字 的题解

    题目背景 实力强大的小A 被选为了ION2018 的出题人,现在他需要解决题目的命名问题. 题目描述 小A 被选为了ION2018 的出题人,他精心准备了一道质量十分高的题目,且已经把除了题目命名以外 ...

  3. 洛谷P4770 [NOI2018]你的名字 [后缀自动机,线段树合并]

    传送门 思路 按照套路,直接上后缀自动机. 部分分:\(l=1,r=|S|\) 首先把\(S\)和\(T\)的后缀自动机都建出来. 考虑枚举\(T\)中的右端点\(r\),查询以\(r\)结尾的串最长 ...

  4. P4770 [NOI2018]你的名字

    蒟蒻表示不会sam凉凉了,所以只能提高SA技巧? 题意:有一个串\(A\),每次选择一个\(A\)的子串\(A'\),以及串\(B\),问\(B\)的所有本质不同子串中不在\(A'\)中的串的数量. ...

  5. 洛谷P4770 [NOI2018]你的名字(后缀自动机+线段树)

    传送门 我有种自己根本没学过SAM的感觉……最后还是抄了老半天的题解…… 首先,对$S$和每一次的$T$都建一个SAM 先考虑一下$l=1,r=\left| S \right|$的情况 设$lim_i ...

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

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

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

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

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

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

  9. [NOI2018]你的名字(68pts)

    SAM真让人头秃. 题面 https://www.luogu.org/problemnew/show/P4770 首先考虑 l=1,r=∣S∣的做法 如果对于ION2018的子串不用判重的话,对ION ...

随机推荐

  1. A1006. Sign In and Sign Out

    At the beginning of every day, the first person who signs in the computer room will unlock the door, ...

  2. BigInteger与BigDecimal

    BigInteger与BigDecimal Java大数字运算(BigInteger类和BigDecimal类) 在 Java 中提供了用于大数字运算的类,即 java.math.BigInteger ...

  3. Runtime.getRuntime().exec(...),当参数中有空格时!

    原以为不会有什么问题,但在测试时发现,问题大了. 如果想调用f:\mp3\i love you.mp3时, 我原以为正确的写法是: //在文件名前后加个双引号来解决文件名中有空格的情况 String ...

  4. 第一篇-ubuntu18.04访问共享文件夹

    1. 在访问Windows共享资料之前,请确保Windows共享是可用的.Linux访问Windows共享或者LInux共享资料给Windows时,都使用Samba软件 rpm -qa | grep ...

  5. jmeter的介绍和使用一

    一,jmeter介绍 1.官方网站下载jmeter,然后解压安装.我用的mac,用mac来讲解. 这是解压以后的包. 2.bin目录里面是一些可执行的文件 ,重点关注启动 如果是windows系统,直 ...

  6. C++ Exception机制

    C++异常机制的执行顺序. 在构造函数内抛出异常 /* * ExceptClass.h * * Created on: 2018年1月2日 * Author: jacket */ #ifndef EX ...

  7. hdu 3415"Max Sum of Max-K-sub-sequence"(单调队列)

    传送门 题意: 给出一个有 N 个数字([-1000 , 1000],N ≤ 105)的环状序列: 让你求一个和最大的连续子序列,并记录起始点. 要求这个连续子序列的长度小于等于K,加和相同的不同区间 ...

  8. TODO 动态执行appium代码,便于修改和调试

    https://testerhome.com/topics/9040 还没尝试过. 不过不是很懂怎么实现的,java不是编译后再运行的语言吗?怎么一边编译一边运行呢???

  9. selenium官方网站文档,testng官方网站文档

    selenium 阅读至grid部分,当前没有远程需求,搁置:https://www.seleniumhq.org/docs/07_selenium_grid.jsp testng http://te ...

  10. JVM与GC

    1.JVM的内存分配参考文章: https://www.cnblogs.com/wangjzh/p/5258254.html 2. java之GC https://www.cnblogs.com/hn ...