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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章