专栏文章
题解:CF1313E Concatenation with intersection
CF1313E题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mineopt6
- 此快照首次捕获于
- 2025/12/02 01:11 3 个月前
- 此快照最后确认于
- 2025/12/02 01:11 3 个月前
给定两个长度为 的字符串 以及一个长度为 的字符串 。问有多少个四元组 满足 。。
一个比较错误的切入点是枚举 贡献的前缀。如果你想要使用后缀数组的话,可以处理出来 对应前缀所能匹配的后缀数组区间以及 后缀的反串在 反串所能匹配的后缀数组区间,然后就转化为了以下问题:
有 组询问,每组询问形如:给定 ,求 。
显然做不了!
事实上,我们需要注意到的一件事情是, 的区间长度总和为 。也就是说,我们只需要保证 并且 即可。
现在我们考虑怎么刻画 与 的计数。
发现在不考虑总长度和为 的情况下, 与 都呈一个区间。
考虑预处理 为 与 的 LCP, 为 与 的 LCS。
我们就能够发现,合法的方案数就恰好为 。有这么一个特判是因为 与 的贡献不能为空。
令 同理,则所求为:
使用你喜欢的数据结构处理即可。时间复杂度 。
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
constexpr int maxn=1e6;
constexpr int base=31;
constexpr int mod=998244353;
int powbase[maxn+5];
struct String{
string s;
vector<int> hsh;
int n;
void init(){
cin>>s;
n=s.length();
s=" "+s;
hsh.resize(n+1,0);
for(int i=1;i<=n;i++){
hsh[i]=(hsh[i-1]*base+s[i])%mod;
//cout<<hsh[i]<<" ";
}
//cout<<"\n";
}
int calc(int l,int r){
// cout<<"Calc "<<l<<" "<<r<<"\n";
return (hsh[r]-hsh[l-1]*powbase[r-l+1]%mod+mod)%mod;
}
char& operator [](int x){
//cerr<<"Call "<<x<<"\n";
return s[x];
}
};
int n,m;
String a,b,s;
int longa[maxn+5],longb[maxn+5];
struct bit{
int v[maxn+5];
void update(int pos,int value){
pos++;
while(pos){
v[pos]+=value;
pos-=pos&(-pos);
}
}
int quary(int pos){
pos++;
int ans=0;
while(pos<=m+1){
ans+=v[pos];
pos+=pos&(-pos);
}
return ans;
}
}ct,v;
signed main(){
ios::sync_with_stdio(0);
cin.tie(nullptr);
powbase[0]=1;
for(int i=1;i<=maxn;i++){
powbase[i]=powbase[i-1]*base%mod;
}
cin>>n>>m;
a.init();
b.init();
s.init();
for(int i=1;i<=n;i++){
if(a[i]!=s[1]){
longa[i]=0;
}
else{
int l=1,r=min(n-i+1,m);
while(l<r){
int mid=((l+r)>>1)+1;
if(a.calc(i,i+mid-1)==s.calc(1,mid)){
l=mid;
}
else{
r=mid-1;
}
}
longa[i]=l;
}
}
for(int i=1;i<=n;i++){
if(b[i]!=s[m]){
longb[i]=0;
}
else{
int l=1,r=min(i,m);
while(l<r){
int mid=((l+r)>>1)+1;
if(b.calc(i-mid+1,i)==s.calc(m-mid+1,m)){
l=mid;
}
else{
r=mid-1;
}
}
longb[i]=l;
}
}
int ans=0;
// for(int l=1;l<=n;l++){
// for(int r=1;r<=n;r++){
// if(r>=l&&r<l+m-1){
// int va=longa[l]-(longa[l]>=m);
// int vb=longb[r]-(longb[r]>=m);
// if(vb>=max(0ll,m-1-va)){
// ans+=va+vb-m+1;
// }
// }
// }
// }
vector<pair<int,int>> quary[n+5];
for(int l=n;l>=1;l--){
int va=m-1-(longa[l]-(longa[l]>=m));//注意此处 va 为题解中的 m-1-va
quary[l].push_back(make_pair(va,1));
if(l+m-1<=n){
quary[l+m-1].push_back(make_pair(va,-1));
}
}
for(int l=n;l>=1;l--){
int vb=longb[l]-(longb[l]>=m);
ct.update(vb,1);
v.update(vb,vb);
for(auto j:quary[l]){
ans+=(-ct.quary(j.first)*(j.first)+v.quary(j.first))*j.second;
}
}
cout<<ans;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...