ZJM 与纸条(KMP算法)

问题描述

ZJM 的女朋友是一个书法家,喜欢写一些好看的英文书法。有一天 ZJM 拿到了她写的纸条,纸条上的字暗示了 ZJM 的女朋友 想给 ZJM 送生日礼物。ZJM 想知道自己收到的礼物是不是就是她送的,于是想看看自己收到的礼物在纸条中出现了多少次。

Input

第一行输入一个整数代表数据的组数

每组数据第一行一个字符串 P 代表 ZJM 想要的礼物, 包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 并且字符串长度满足 1 ≤ |P| ≤ 10,000 (|P| 代表字符串 P 的长度).

接下来一行一个字符串 S 代表 ZJM 女朋友的纸条, 也包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 满足 |P| ≤ |S| ≤ 1,000,000.

Output

输出一行一个整数代表 P 在 S中出现的次数.

Sample input

3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Sample output

1
3
0

解题思路

这个题是一道字符串匹配问题,因此我们可以用到KMP算法,这是一道经典的字符串匹配算法,其中next数组的思想十分重要(AC自动机中也用到了这个数组)。KMP讲解可以看一下这个链接

KMP的时间复杂度可以达到O(m+n)O(m+n)。我用Sunday算法尝试了一下这个题,结果TLE了,不知道是数据卡Sunday还是我自己改Sunday改错了。Sunday有点不稳定,平均复杂度O(n)O(n),最坏O(nm)O(n*m)。有兴趣的可以看一下这个博客

完整代码

//#pragma GCC optimize(2)
//#pragma G++ optimize(2)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

const int maxn=10000+10;
const int maxm=1000000+10;
int nxt[maxn],ans,n;
char ptr[maxn],str[maxm];
void get_next(const char ptr[],int len){
    nxt[0]=0;
    for (int i=1,j=0; i<len; i++){
        while(j && ptr[j]!=ptr[i]) j=nxt[j-1];
        if(ptr[j]==ptr[i]) j++;
        nxt[i]=j;
    }
}
int kmp(const char str[],const char ptr[]){
    int len1=strlen(str);
    int len2=strlen(ptr);
    int j=0;
    get_next(ptr,len2);
    for (int i=0; i<len1; i++){
        while(j && ptr[j]!=str[i]) j=nxt[j-1];
        if(ptr[j]==str[i]) j++;
        if(j==len2){
            ans++;
            j=nxt[j-1];
        }
    }
    return ans;
}
int getint(){
    int x=0,s=1; char ch=' ';
    while(ch<'0' || ch>'9'){ ch=getchar(); if(ch=='-') s=-1;}
    while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar();}
    return x*s;
}
int main(){
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    scanf("%d",&n);
    while(n--){
        memset(ptr,0,sizeof(ptr));
        memset(str,0,sizeof(str));
        memset(nxt,0,sizeof(nxt));
        ans=0;
        scanf("%s",ptr);
        scanf("%s",str);
        printf("%d\n",kmp(str,ptr));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章