• KMP的正确使用法_x新疆网络赛Query on a string


    Query on a string

    题意,给定一个大字符串,给定一个小模式串,定义 两种不同的任务模式,分别是查询和更改:

    查询对应区间内,有多少个匹配到位的数字;

    修改某一位的某一个字母。

    于是直觉告诉我们是KMP,而且需要一个单点更新,动态查询的数据结构——直觉上认为树状数组比较合适执行这个任务。

    于是,开个大大数组,保存每次匹配时对应位的四字母的匹配指针的位置。

    每次扫描到了模式串长度都往树状数组里面存入相关元素。

    每次修改之后应当从新就地走一遍模式串,更新相关内容,注意,每次匹配到的新的结果和老结果向同的时候就应当退出。

    #include<bits/stdc++.h>
    using namespace std;
    
    const long long MAXN=200233;
    char str[MAXN];
    char str2[23];
    int lenOfSub;
    int flags[MAXN];
    int f[MAXN];
    
    
    int n,m;
    
    int tree[MAXN];
    void insert(int pos,int key)
    {
        pos+=23;
        while(pos<MAXN)
        {
            tree[pos]+=key;
            pos+=pos&(-pos);
        }
    }
    int getSum(int pos)
    {
        pos+=23;
        int ret=0;
        while(pos)
        {
            ret+=tree[pos];
            pos-=pos&(-pos);
        }return ret;
    }
    
    
    void get_fail()
    {
        int len=strlen(str2);
        lenOfSub=len;
        f[0]=f[1]=0;
        for(int i=1;i<len;++i)
        {
            int j=f[i];
            while(j&&str2[i]!=str2[j])j=f[j];
            f[i+1]= str2[i]==str2[j]? j+1:0;
        }
    }
    void get_match()
    {
        int j=f[0];
        int len=strlen(str);
        for(int i=0;i<len;++i)
        {
            while(j&&str[i]!=str2[j])j=f[j];
            j= str[i]==str2[j]? j+1:0;
            flags[i]=j;
        }
    //    for(int i=0;i<len;++i)cout<<flags[i]<<ends;
    //    cout<<endl;
    }
    
    
    void init()
    {
        scanf("%d
    ",&n);
        memset(tree,0,sizeof(tree));
        memset(f,0,sizeof(f));
        gets(str);
        gets(str2);
        get_fail();
        get_match();
        int len=strlen(str);
        for(int i=1;i<len;++i)
        {
            if(flags[i]==lenOfSub)insert(i,1);
        }
        for(int it=0;it<n;++it)
        {
            char cm[2];
            scanf("%s",cm);
            
            if(cm[0]=='Q')
            {
                int pos1;int pos2;
                scanf("%d%d",&pos1,&pos2);pos1--;pos2--;
                int poss=-1;int j=f[0];
                    int ans=0;
                for(int i=pos1;i<=pos2;++i)
                {
                    while(j&&str[i]!=str2[j])j=f[j];
                    j= str[i]==str2[j]? j+1:0;
                    if(j==lenOfSub)ans++;
                    if(j==flags[i])
                    {
                        poss=i;
                        break;
                    }
                }
                if(poss==-1)
                {
                    cout<<ans<<"
    ";
                }else
                {
                    cout<<ans+(getSum(pos2)-getSum(poss))<<"
    ";
                }
                
            }else
            {
                int pp;
                scanf("%d%s",&pp,cm);
                pp--;
                str[pp]=cm[0];
                int j=0;
                if(pp)j=flags[pp-1];
                for(int i=pp;i<len;++i)
                {
                    while(j&&str[i]!=str2[j])j=f[j];
                    j= str[i]==str2[j]? j+1:0;
                    if(flags[i]==j)break;
                    if(flags[i]==lenOfSub)insert(i,-1);
                    if(j==lenOfSub)insert(i,1);
                    flags[i]=j;
                }
            }    
        } 
        
        cout<<"
    ";
    }
    
    int main()
    {
        cin.sync_with_stdio(false);
        
        int t;
        scanf("%d",&t) ;
        while(t--)init();
        
        
        return 0;
        
    } 
  • 相关阅读:
    python正则去掉html标签里的css内容
    elasticsearch scroll
    js控制滚动条自动往下滑动
    Pandas导出Excel的时候出现openpyxl.utils.exceptions.IllegalCharacterError异常问题
    C# 动态构建表达式树(二)——构建 Select 和 GroupBy 的表达式
    C# 动态构建表达式树(一)—— 构建 Where 的 Lambda 表达式
    C# 中 async 和 await 的基本使用
    C# 中 AppDomain 的一些理解
    win10家庭版 无法修改hosts文件
    我的第一个Scala程序
  • 原文地址:https://www.cnblogs.com/rikka/p/7594628.html
Copyright © 2020-2023  润新知