文章目录
- 题目大意
- 题解
- 参考代码
题目大意
题解
注意
∑
∣
t
∣
≤
2
∗
1
0
6
\sum{|t|} \leq 2*10^6
∑∣t∣≤2∗106。
对于每一组操作
2
2
2 我们发现可以用
k
m
p
kmp
kmp 处理,复杂度为
2
∗
∣
s
∣
2*|s|
2∗∣s∣ 。
明显的,当
s
i
z
t
<
s
i
z
s
siz_t <siz_s
sizt<sizs 时,不存在出现的次数,答案为
0
0
0 。
筛掉了一部分的
t
t
t ,复杂度最多为
O
(
2
∗
∣
s
∣
∗
(
2
∗
1
0
6
/
∣
s
∣
)
)
O(2*|s|*(2*10^6/|s|))
O(2∗∣s∣∗(2∗106/∣s∣)) ,即
O
(
4
∗
1
0
6
)
O(4*10^6)
O(4∗106)
所以,跑裸的
k
m
p
kmp
kmp 统计长度和个数即可。
参考代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int s,m,b,p,ans,c;
long long z;
int f[N];
int g[N];
int nxt[N];
signed main()
{
cin>>s>>m>>b>>p;
for(int i=1;i<=s;i++)
scanf("%lld",&f[i]);
c=1;
for(int k=1;k<=m;k++)
{
int op;
scanf("%lld",&op);
if(op==1)
{
int x,c;
scanf("%lld%lld",&x,&c);
x=(x^z)%(s)+1; //强制在线操作
c=c^z;
f[x]=c;
// cout<<"1"<<endl;
// cout<<x<<" "<<c<<endl;
}
else
{
c=1ll*c*b%p;
int n,x=0,y=0;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
int a;
scanf("%lld",&a);
g[i]=a^z;
// cout<<g[i]<<" ";
}
// puts("");
if(n<s)
{
z=0;
continue;
}
int k=0;
nxt[1]=0;
for(int i=2;i<=s;i++) //kmp
{
while(f[k+1]!=f[i] && k!=0)
k=nxt[k];
if(f[k+1]==f[i])
k++;
nxt[i]=k;
}
k=0;
for(int i=1;i<=n;i++)
{
while(f[k+1]!=g[i] && k!=0)
k=nxt[k];
if(f[k+1]==g[i])
k++;
if(k==s)
{
x++; //更新个数
if(i==n)
break;
k=nxt[k];
}
// cout<<k<<endl;
}
k=nxt[s]; //r
z=x*k;
// cout<<x<<" "<<k<<endl;
// cout<<z<<" "<<"z"<<endl;
ans=(1ll*ans+1ll*k*x%p*c%p)%p; //计算答案
}
}
printf("%lld\n",ans);
}