前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >POJ 3461 字符串匹配(KMP / 哈希(有推导))

POJ 3461 字符串匹配(KMP / 哈希(有推导))

作者头像
Michael阿明
发布2021-02-20 10:46:49
4460
发布2021-02-20 10:46:49
举报
文章被收录于专栏:Michael阿明学习之路

1. 题目

1.1 题目链接

http://poj.org/problem?id=3461

类似题目:LeetCode 30. 串联所有单词的子串(字符串哈希)

1.2 题目大意

模式串在主串中出现过几次。

2. Accepted代码

2.1 KMP解法

代码语言:javascript
复制
#include <stdio.h>
#include <iostream>
#include <cstring>
int next[10001];
char a[1000001], b[10001];
void calNexts(char *b, int m, int *next)
{
    next[0] = -1;
    int j = 0, k = -1;
    while(j < m)
    {
        if(k == -1 || b[j] == b[k])
        {
            j++;k++;
                next[j] = k;
        }
        else
            k = next[k];
    }
}
int str_kmp(char *a, int n, char *b, int m)
{
    calNexts(b, m, next);
    int i = 0, j = 0, times = 0;
    while(i < n && j < m)
    {
        if(j == -1 || a[i] == b[j])
        {
            i++;j++;
        }
        else
        {
            j = next[j];
        }
        if(j == m)
        {
            times++;
            j = next[j];
        }
    }
    return times;
}
int main()
{
    int count;
    std::cin >> count;
    while(count--)
    {
        scanf("%s",&b);
        scanf("%s",&a);
        printf("%d\n",str_kmp(&a[0], strlen(a), &b[0], strlen(b)));
    }
    return 0;
}

2.2 哈希法(有推导过程)

参考别人的哈希函数,哈希值的求法很犀利

自己推导的过程如下:

代码语言:javascript
复制
/**
 * @description: poj 3461 字符串匹配,哈希法
 * @author: michael ming
 * @date: 2019/6/26 21:59
 * @modified by: 
 */
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#define K 25    //K大于等于字符集数 k>=25
typedef unsigned long long ull;
char a[1000001], b[10001];
ull ha[1000001];
ull powk[10001];//存储K的幂值
using namespace std;
void fillpowk(int m)
{
    powk[0] = 1;
    for(int i = 1; i <= m; ++i)
        powk[i] = powk[i-1]*K;
}
ull hashf(int m, char *str)
{
    ull value = 0;
    for(int i = 0; i < m; ++i)
        value = value * K + str[i];
    return value;
}
int str_RK(char *a, int n, char *b, int m)//a是主串,b是模式串
{
    fillpowk(m);
    int i, times = 0;
    ull hash_val, value = 0;
    value = hashf(m,b); //计算模式串的hash值value
    ha[0] = ull(a[0]);
    for(i = 1; i < n; ++i)
        ha[i] = ha[i-1] * K + a[i];
    for(i = 0; i < n-m+1; ++i)//最多n-m+1次比较
    {
        if(i == 0)
            hash_val = hashf(m,a);
        else
            hash_val = ha[i+m-1] - ha[i-1]*powk[m];
            //这个公式可以自己推导一下
        if(hash_val == value)
        {//如果子串哈希值等于模式串的,匹配成功(该哈希无冲突)
            times++;
        }
    }
    return times;
}
int main()
{
    int count;
    std::cin >> count;
    while(count--)
    {
        scanf("%s",&b);
        scanf("%s",&a);
        printf("%d\n",str_RK(&a[0], strlen(a), &b[0], strlen(b)));
    }
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/06/26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 题目
    • 1.1 题目链接
      • 1.2 题目大意
      • 2. Accepted代码
        • 2.1 KMP解法
          • 2.2 哈希法(有推导过程)
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档