poj3461(KMP算法)||(字符串hash)

原创 2018年04月16日 22:02:44

题意:给出两个字符串,然你判断第一个字符串在第二个字符串中出现的次数。

思路:一个裸的KMP算法。主要内容在下面代码中实现。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int t;
string a, s;//a是待匹配字符,s是需要查找的内容
const int maxn = 10005;
int Next[maxn];//Next[i]表示前i位的前后缀匹配位数,字符串从下标0开始
void tran() {
    memset(Next, 0, sizeof(Next));
    for(int i = 1; i < s.size(); i++) {
        int j = Next[i - 1];//根据KMP算法,当前Next的大小是根据前一位而来的,分为3种情况
        //一是j==0,二是j!=0且s[i]!=s[j],三是j!=0但是s[i]==s[j]
        while(j && s[i] != s[j]) j = Next[j - 1];//如果前一位不为1且不匹配,那么就回溯,就是第2种情况
        Next[i] = (s[i] == s[j]) ? j + 1 : 0;//这里包括了第一种和第三种情况
    }
}
int  solve() {
    tran();
    int ans = 0;//这是子串数量
    int j = 0;//当前位于s[j]的位置
    for(int i = 0; i < a.size(); i++) {
        while(j && a[i] != s[j]) j = Next[j - 1];//如果当前匹配失败,寻找是否符合的前后缀
        if(a[i] == s[j])j++;//如果当前能够匹配,就j++,尝试下一个s的字符
        if(j == s.size()) {
            ans++ ;
            j = Next[j - 1];//当完成匹配的时候需要将j回溯,感谢大佬的纠错
        } //如果已经位于s的最后,说明成功完成匹配一次
    }
    return  ans;
}
int main() {
    scanf("%d", &t);
    while(t--) {
        cin >> s >> a;
        printf("%d\n", solve());
    }

    return 0;
}

————————————————————————————————————————
2018年4月22日更新
这两天学了一下字符串哈希,于是重做了此题,下面贴上代码:

#include <cstring>
#include <iostream>
#include <map>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
const int maxn = 1e7 + 5;
const ull has = 2333;
char s1[maxn], s2[maxn];
int Hash() {
    int len1 = strlen(s1+1);
    int len2 = strlen(s2+1);
    int cnt = 0;
    ull ll = 1;
    ull a1 = 0;
    ull a2 = 0;
    for(int i = 1; i <= len1; ++i) {
        ll *= has;
        a1 = a1 * has + s1[i] ;
        a2 = a2 * has + s2[i] ;
    }
    if(a1 == a2) cnt++;
    for(int i = len1+1 ; i  <= len2; ++i) {
        a2 = a2 * has + s2[i] - ll * (s2[i - len1] );
        if(a1 == a2) cnt++;
    }
    return cnt;
}
int t;
int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%s%s", s1+1, s2+1);
        printf("%d\n", Hash());
    }
    return 0;
}
版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/79967418

彻底掌握 Javascript(七)字符串【专家辅导】

-
  • 1970年01月01日 08:00

POJ3461 字符串hash

//为了防止冲突,使用了双hash #include #include #include #include #include #define ull unsigned long long const ...
  • sxy_cnyali
  • sxy_cnyali
  • 2016-02-01 17:02:26
  • 8099

poj3461 hash字符串匹配

可以用KMP写,然而发现hash不用写很长,而且好理解。 定义一个匹配串的hash值为c[1]b^ (m - 1) + c[2]b^(m - 2) + …… + c[m - 1]b + c[m]; 然...
  • xiaolonggezte
  • xiaolonggezte
  • 2017-09-05 17:48:06
  • 108

【poj 3461】Oulipo hash求子串hash值

我靠,这道题卡时限太厉害了吧,我用大质数取模居然能T,最好无赖改成了unsigned long long自然溢出才过,不过这样写hash很容易被卡啊。用hash过一次 字串hash公式 hash[l...
  • pbihao
  • pbihao
  • 2016-11-10 22:22:33
  • 92

字符串hash - POJ 3461 Oulipo

Oulipo  Problem's Link ------------------------------------------------------------------...
  • u013371163
  • u013371163
  • 2017-03-05 17:13:38
  • 139

poj 3461 字符串单串匹配--KMP或者字符串HASH

http://poj.org/problem?id=3461 先来一发KMP算法: #include #include #include #include #include #inc...
  • u011026968
  • u011026968
  • 2014-08-09 21:11:53
  • 1005

POJ3461 字符串HASH

#include #include #include #define ull unsigned long long const ull B = 1e8+7; const int MAXN...
  • cnyali
  • cnyali
  • 2015-08-09 12:38:01
  • 435

poj2503字符串HASH

HASH是一种极其有益的算法,俗称标记法,主要用途是从大量数据中找到某一些问题的答案。 和线段树差不多,不过线段树是搜寻相对应的量,而HASH则是一个单独的量。 比较有难度,而字符串HASH则是提高+...
  • cnyali_ljf
  • cnyali_ljf
  • 2016-05-07 22:08:09
  • 1467

KMP替代算法——字符串Hash

KMP替代算法——字符串Hash 今天来谈谈一种用来替代KMP算法的奇葩算法——字符串Hash 例题:给你两个字符串p和s,求出p在s中出现的次数。(字符串长度小于等于1000000) ...
  • gywenjian
  • gywenjian
  • 2018-02-01 17:23:40
  • 53

POJ3461 KMP算法

Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, with...
  • a305657
  • a305657
  • 2013-01-31 22:00:39
  • 308
收藏助手
不良信息举报
您举报文章:poj3461(KMP算法)||(字符串hash)
举报原因:
原因补充:

(最多只允许输入30个字)