zoukankan      html  css  js  c++  java
  • HihoCoder1084: 扩展KMP(二分+hash,求T串中S串的数量,可以失配一定次数)

    时间限制:4000ms
    单点时限:4000ms
    内存限制:256MB

    描述

    你知道KMP吗?它是用于判断一个字符串是否是另一个字符串的子串的算法。今天我们想去扩展它。

    在信息理论中,在两个相同长度的字符串之间的海明码距离是:两个字符串相同位置对应的字符不同的位置数目。换种说法,它表示将一个字符串转化为另一个字符串所需要改变字符的最小数目。

    下面这些字符串之间的海明码距离:

    "karolin"和"kathrin"是3.

    "karolin"和"kerstin"是3.

    1011101和1001001是2.

    2173896和2233796是3.

    现在给定两个字符串stra,strb,和一个整数k。对于stra中的一个子串,如果它的长度和strb的相同且它们之间的海明码距离不超过k,我们认为它们是匹配的。

    那么我们想知道在stra中有多少子串是和strb是匹配的。

    输入

    有多组测试(大约100),每个用例占3行。

    第一行是stra。

    第二行是strb。

    第三行是k。

    请处理到文件末尾。

    【参数说明】

    1<=stra,strb的长度<=100000

    stra,strb只包含小写字母

    0<=k<=5

    输出

    对于每个测试用例,以输出结果占一行。

    样例输入
    abcde
    f
    0
    abcde
    f
    1
    karolin
    kathrin
    3
    样例输出
    0
    5
    1

    题意:求T串中S串的数量,最多可以失配K。

    思路:len1=|S|,len2=|T|。枚举S的起点i,如果i后面的可行的长度>=len2,则累加1次。

    具体实现:二分得到当前最长匹配长度,假设是L,则跳过L后面一位(失配的一位),同时失配次数累加一次,继续检测后面的。 如果匹配成功,而且跳过次数不超过K次,则满足。

    Bkdrhash+二分: (题目是ExKMP,我没想到这么用扩展kmp来做,qwq。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define ull unsigned long long
    const int maxn=100000;
    const int seed=131;
    char a[maxn+10],b[maxn+10];
    int hash1[maxn+10],hash2[maxn+10],g[maxn+10],K;
    int L1,L2,ans;
    int find(int w,int v)
    {
        int L=1,R=L2-v+1,res=0;
        while(L<=R){
            int Mid=(L+R)>>1;
            if(hash1[w+Mid-1]-hash1[w-1]*g[Mid]==hash2[v+Mid-1]-hash2[v-1]*g[Mid]) res=Mid,L=Mid+1;
            else R=Mid-1; 
        } return res;
    }
    bool check(int x)
    {
        int w=x,v=1;
        for(int i=1;i<=K;i++){
            int L=find(w,v);
            w=w+L+1; v=v+L+1;
            if(v>L2) return true;
        }
        int L=find(w,v);
        w=w+L; v=v+L;
        if(v>L2) return true;
        return false;
    }
    int main()
    {
        g[0]=1;
        for(int i=1;i<=maxn;i++) g[i]=g[i-1]*seed;
        while(~scanf("%s%s%d",a+1,b+1,&K)){
            L1=strlen(a+1); L2=strlen(b+1); ans=0;
            for(int i=1;i<=L1;i++) hash1[i]=hash1[i-1]*seed+a[i];
            for(int i=1;i<=L2;i++) hash2[i]=hash2[i-1]*seed+b[i];
            for(int i=1;i<=L1-L2+1;i++) 
               if(check(i))  ans++;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    XSS之防御与绕过
    说说XXE漏洞那些事
    常见web中间件漏洞(五)weblogic漏洞
    DLL劫持漏洞
    常见web中间件漏洞(四)Tomcat漏洞
    常见web中间件漏洞(三)Nginx漏洞
    CNVD-2021-14536 锐捷 RG-UAC 统一上网行为管理审计系统信息泄露漏洞
    Jupyter安装并设置反向搭理
    读书-刑罚的历史
    读书-反常识
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8524787.html
Copyright © 2011-2022 走看看