CF316G3 - Good Substrings
有点厉害。
首先给一个
然后,我们把
最后将所有的限制区间取交集,得到每个位置可用的答案区间。这还没完,因为我们需要的是原串本质不同的子串,所以需要再建一个
struct node{
int len,sz,pa,ss,nxt[26];
node(){
len=0,sz=0,pa=0;
rd(i,26)nxt[i]=0;
}
}s[100005];
vt<int>vv[100005];
int lst,cnt,ss[100005];
inline void add(int c,int v){
int x=lst;s[++cnt]=node();
s[cnt].len=s[lst].len+1;
s[lst=cnt].sz=1;ss[cnt]=v;
for(;x&&!s[x].nxt[c];x=s[x].pa)s[x].nxt[c]=cnt;
if(!x)return (void)(s[cnt].pa=1);
int to=s[x].nxt[c];
if(s[x].len+1==s[to].len){
return(void)(s[cnt].pa=to);
}
s[++cnt]=s[to];
s[cnt].sz=0;
s[cnt].len=s[x].len+1;
for(;x&&s[x].nxt[c]==to;x=s[x].pa)s[x].nxt[c]=cnt;
s[cnt-1].pa=s[to].pa=cnt;
}
int l,r,L[100005],R[100005];
inline void dfs(int x){
for(auto j:vv[x]){
dfs(j);
s[x].sz+=s[j].sz;
ss[x]=ss[j];
}
if(l<=s[x].sz&&s[x].sz<=r){
L[x]=s[s[x].pa].len+1;
R[x]=s[x].len;
}else L[x]=114514,R[x]=0;
}
inline void getcur(int x){
if(x!=1)L[x]=min(L[x],L[s[x].pa]),R[x]=max(R[x],R[s[x].pa]);
for(auto j:vv[x])getcur(j);
}
inline void build(string t){
cnt=1,lst=1,s[1]=node();
rd(i,(int)t.size())add(t[i]-'a',i);
rp(i,cnt)vv[i].clear();
rep(i,2,cnt)vv[s[i].pa].pb(i);
dfs(1);s[1].sz=0;getcur(1);
}
int ans=0;
int ansl[50005],ansr[50005];
inline void solve(int x){
l=s[s[x].pa].len+1,r=R[x]=s[x].len;
l=max(l,ansl[ss[x]]);
r=min(r,ansr[ss[x]]);
ans+=max(0,r-l+1);
for(auto j:vv[x])solve(j);
}
st T,S;
int n,m,cx=0;
inline int trans(int x,int c){
while(x&&!s[x].nxt[c])x=s[x].pa,cx=min(cx,s[x].len);
if(x){
cx++;
return s[x].nxt[c];
}
return 1;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>T>>n;
m=T.size();
rd(i,m)ansl[i]=1,ansr[i]=i+1;
rp(_,n){
cin>>S>>l>>r;
if(r>0){
build(S);
cx=0;
for(int x=1,i=0;i<m;i++){
x=trans(x,T[i]-'a');
if(l==0&&L[x]==114514);
else ansl[i]=max(ansl[i],L[x]);
if(l!=0)ansr[i]=min({ansr[i],R[x],cx});
}
}else{
build(S);
cx=0;
for(int x=1,i=0;i<m;i++){
x=trans(x,T[i]-'a');
ansl[i]=max(ansl[i],s[x].len+1);
}
}
}
build(T);
solve(1);
cout<<ans<<endl;
return 0;
}
//Crayan_r
然后是
然后,我们枚举
我们可以预处理每个
然后还是合并各个限制答案,我们就得到了对于每个后缀,长度是多少的子串满足要求。
最后就是统计本质不同子串的答案。我们可以在原串上按照排名依次来,当前串
然后就可以通过了。
两种做法的内在联系
实际上我们就是用
我们第一个程序用
后面统计答案的过程就更加相似了。其实一直都是基于查找相同
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】