文章目录
- 题目大意
- 题解
- 参考代码
题目大意

题解
注意  
     
      
       
       
         ∑ 
        
        
        
          ∣ 
         
        
          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);
}


















