2023牛客暑期多校训练营7 L.Misaka Mikoto‘s Dynamic KMP Problem(KMP))

文章目录

  • 题目大意
  • 题解
  • 参考代码

题目大意

2023牛客暑期多校训练营7 L.Misaka Mikoto‘s Dynamic KMP Problem(KMP))_第1张图片

题解

注意 ∑ ∣ t ∣ ≤ 2 ∗ 1 0 6 \sum{|t|} \leq 2*10^6 t2106
对于每一组操作 2 2 2 我们发现可以用 k m p kmp kmp 处理,复杂度为 2 ∗ ∣ s ∣ 2*|s| 2s
明显的,当 s i z t < s i z s siz_t sizt<sizs 时,不存在出现的次数,答案为 0 0 0
筛掉了一部分的 t t t ,复杂度最多为 O ( 2 ∗ ∣ s ∣ ∗ ( 2 ∗ 1 0 6 / ∣ s ∣ ) ) O(2*|s|*(2*10^6/|s|)) O(2s(2106/∣s)) ,即 O ( 4 ∗ 1 0 6 ) O(4*10^6) O(4106)
所以,跑裸的 k m p kmp kmp 统计长度和个数即可。

参考代码

#include
#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"<
//             cout<
        }
        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<
            }
//             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=nxt[s];            //r
            z=x*k;
//             cout<
//             cout<
            ans=(1ll*ans+1ll*k*x%p*c%p)%p;              //计算答案
        }
    }
    printf("%lld\n",ans);
}

你可能感兴趣的:(c++)