KMP算法解决字符串匹配

该算法由D.E.Knuth ,J.H.Morris和 V.R.Pratt提出,用于解决字符串匹配问题。

思想:

设目标串(主串)为s,模式串为t ,并设i指针和j指针分别指示目标串和模式串中正待比较的字符,设i和j的初值均为0。若有s[i]=t[j],则i和j分别加1。否则,i不变,j退回到j=next[j-1]的位置,再比较s[i]和t[j],若相等,则i和j分别加1。否则,i不变,j再次退回到j=next[j]的位置,依此类推。直到下列两种可能:

1. 模式串t中的字符全部匹配,则出现频率+1

2. 退回到j=0,将i加1,即从主串的下一个字符s[i+1]与模式串t[0]处重新开始匹配。

什么是next数组?

next数组是对模式串t中各元素位置下的一种历史信息记录。它的数学定义为:

next[i] = max{0<=k<=i|t.substring(0,k) == t.substring(i-k+1,k)}

其中:t.substring(i,k)表示t从索引i开始的k个字符的子串。

例如模式串t:bababb,其next数组为{0,0,1,2,3,1}.

如何求next数组?

求解next数组其实也是利用kmp思想。初始时next[0]=0.

对于next[i],我们将t.substring(0,i+1)作为目标串,将t.substring(0,i)作为模式串,根据q =next[i-1],只要有t[i]==t[q],则next[i] = q+1;否则q = next[q-1]继续类推,直到退回到q=0,此时表示next[i]=0.

题目

#1015 : KMP算法


输入

第一行一个整数N,表示测试数据组数。

接下来的N*2行,每两行表示一个测试数据。在每一个测试数据中,第一行为模式串,由不超过10^4个大写字母组成,第二行为原串,由不超过10^6个大写字母组成。

其中N<=20

输出

对于每一个测试数据,按照它们在输入中出现的顺序输出一行Ans,表示模式串在原串中出现的次数。

样例输入

5

HA

HAHAHA

WQN

WQN

ADA

ADADADA

BABABB

BABABABABABABABABB

DAD

ADDAADAADDAAADAAD

样例输出

3

1

3

1

0


代码

#include<stdio.h>
#include<string.h>
#define S_LEN 1000005
#define T_LEN 10005

char t[T_LEN];
char s[S_LEN];

int next[T_LEN];

//求解next数组
void solve_next(){
    int t_len = strlen(t);
    memset(next, 0, t_len*sizeof(int));
    int p,q;
    for (p = 1; p < t_len; p++){
        q = next[p - 1];
        while (1){
            if (t[p] == t[q]) {
                next[p] = q + 1; break;
            }
            if (!q) break;
            q = next[q - 1];
        }
    }
}

//查找匹配
int kmp() {
    int t_len = strlen(t);
    int s_len = strlen(s);
    if (t_len > s_len) return 0;
    int ans = 0, i = 0, j = 0;
    while (j < s_len){
        while (i < t_len&&j < s_len && t[i] == s[j]) {
            i++; j++;
        }
        if (i == t_len) ans++;
        if (!i) j++;
        else i = next[i - 1];
    }
    return ans;
}

int main(void){
    int N,i;
    scanf("%d", &N);
    for (i = 0; i < N; i++){
        scanf("%s%s", t, s);
        solve_next();
        printf("%d\n", kmp());
    }
    return 0;
}
结果 语言 时间 内存
AC GCC 46ms 7MB

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-03 21:31:04

KMP算法解决字符串匹配的相关文章

KMP算法实现字符串匹配

#include<stdio.h> #include<string> #include<iostream> using namespace std; int main() { string str,p; cin>>str>>p; int n=str.length(); int m=p.length(); //compute prefix function int pre[100]; pre[0]=-1; int k=-1; for(int j=1

【算法】字符串匹配之Z算法

在很长一段时间,求文本与单模式串匹配,我只用KMP.后来我在CF上看到Z算法,用的人也不少.在学习之后,我感觉Z算法也是很精妙的.在以前的博文中也有过用Z算法来解决字符串匹配的题目. 下面介绍一下Z算法. 先一句话讲清楚Z算法能求什么东西. 输入为一个字符串s,Z算法可以求出这个字符串每一个后缀与自身的最长公共前缀LCP. 接下来,介绍Z算法的具体内容. 记字符串s的长度为n. Z算法需要维护一对值,记为left和right,简记为L和R.L和R满足s[L,R]为s串的前缀.当i为1的时候,暴力

运用kmp算法解决的一些问题的简单题解

学习kmp算法我最后是看的数据结构书上的一本教材学会的..我觉得kmp相对于普通的BF算法就是避免了很多不必要的匹配,而kmp算法的精髓自然就在于next数组的运用...而next数组简而言之就是存储的就是模式串中第j个字符与主串中相应字符"失配"时,在模式串中需要重新和主串中失配的字符相比较的位置...我觉得这句概括挺好的... 题1: hdu   1711  number   sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?

KMP算法类习题——字符串匹配

Description For each prefix with length P of a given string S,if S[i]=S[i+P] for i in [0..SIZE(S)-p-1], then the prefix is a “period” of S. We want to all the periodic prefixs. Input Input contains multiple cases. The first line contains an integer T

字符串匹配暴力算法 与 字符串匹配的KMP算法

声明:先看一下阮一峰的网络日志关于字符串的KMP算法的讲解.本文图片均引用于这篇日志. 在先前的笔试中遇到了关于字符串匹配的问题,一时脑袋卡壳没写好算法.现在就来分析分析 暴力算法和KMP算法各自原理,以及代码实现,之间差异,并且总结一下好算法的一般思路. =========================================================================== 各自原理: 暴力算法: 1. 我们把长的字符串做为一个文本字符串,命名为strText,把

数据结构与算法简记--字符串匹配KMP算法

KMP算法 比较难理解,准备有时间专门啃一下. 核心思想与BM算法一样:假设主串是 a,模式串是 b.在模式串与主串匹配的过程中,当遇到不可匹配的字符的时候,我们希望找到一些规律,可以将模式串往后多滑动几位,跳过那些肯定不会匹配的情况. 不同的是:在模式串和主串匹配的过程中,把不能匹配的那个字符仍然叫作坏字符,把已经匹配的那段字符串叫作好前缀. 关键找相等的最长匹配前缀和最长匹配后缀.有两种情况,(1)如果b[i-1]的最长前缀下一个字符与b[i]相等,则next[i]=next[i-1]+1.

【数据结构与算法】字符串匹配KMP算法

首先需要了解一下BF暴力匹配算法,这个算法为每一个串设置一个指针,然后两个指针同时后移,出现不匹配的情况后,主串指针回到开始后移之前的位置的下一位,模式串指针回到最开始. 对比一下KMP算法,同样是设置两个指针,然后两个指针同时后移,出现不匹配的情况后,主串指针不变,模式串指针回溯一定的距离.具体模式串指针回溯多少,是第一次看KMP算法的人比较难以理解的,其实仔细想想,模式串的前缀和后缀其实也是在做匹配,当P[K]!=P[J]时就是失配,那么前缀的指针就需要回溯,所以后k=next[k]. 代码

Boyer Moore算法(字符串匹配)

上一篇文章,我介绍了KMP算法. 但是,它并不是效率最高的算法,实际采用并不多.各种文本编辑器的"查找"功能(Ctrl+F),大多采用Boyer-Moore算法. Boyer-Moore算法不仅效率高,而且构思巧妙,容易理解.1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了这种算法. 下面,我根据Moore教授自己的例子来解释这种算法. 1. 假定字符串为"HERE IS A SIMPLE EXAMPLE",搜

(原创)数据结构之利用KMP算法解决串的模式匹配问题

给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串S中出现的位置. 输入格式: 输入有两行: 第一行是主串S: 第二行是模式T. 输出格式: 输出相匹配的子串中的第一个字符在主串S中出现的位置.若匹配失败,输出0. 输入样例: 在这里给出一组输入.例如: aaaaaba ba 输出样例: 在这里给出相应的输出.例如: 6 解题思路:串的模式匹配有两种:一种是BF算法,一种是KMP算法:基于这道题给的数