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

版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/79967418

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

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

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include  <string>
using namespace std;
int n;
const int maxn = 1e4 + 5;
char a[maxn * 100], s[maxn];//a是待匹配字符,s是需要查找的内容

int Next[maxn];//Next[i]表示前i位的前后缀匹配位数,字符串从下标0开始

void init() {
    memset(Next, 0, sizeof(Next));
    int len=strlen(s);
    for(int i = 1; i <len; 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() {
   int ans = 0;//这是子串数量
    int j = 0;//当前位于s[j]的位置

int len1=strlen(a);
int len2=strlen(s);
    for(int i = 0; i < len1; i++) {
        while(j && a[i] != s[j]) j = Next[j - 1];//如果当前匹配失败,寻找是否符合的前后缀
        if(a[i] == s[j])j++;//如果当前能够匹配,就j++,尝试下一个s的字符
        if(j == len2) {
            ans++ ;
           //好像不需要? j = Next[j - 1];//当完成匹配的时候需要将j回溯,感谢大佬的纠错
        } //如果已经位于s的最后,说明成功完成匹配一次

    }

    return ans;
}
int main() {
    scanf("%d", &n);
    while(n--) {
        scanf("%s%s", s, a);
        init();
        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;
}
阅读更多
想对作者说点什么? 我来说一句
相关热词

没有更多推荐了,返回首页