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\n",ans);
    }
    return 0;
}

优质内容筛选与推荐>>
1、PHP 基础篇 - PHP 中 DES 加解密详解
2、apt-get update : pulic key error
3、git回溯到指定版本
4、四、OpenStack—glance组件介绍与安装
5、Prometheus Alertmanager 介绍详解


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn