字符串查找KMP算法

如果你用过ctrl+F这个快捷键,那么你有很大的概率使用过这个算法,这就是在待查找字符串(可能有成千上万个字符)中找出模式串(比较小,可能有几个字符),可能找到大于或者等于1次的位置。例如,在ababcd中找出abc。这里介绍算法思想,只给出了第一次出现的位置。

一.算法思想

传统算法是从匹配串第一字符开始和模式串比较,直到遇到不符合的字符,然后从匹配串的下一个字符开始,重复上面的过程。代码如下:

void find(char t[],char p[]){
    int m = strlen(t);
    int n = strlen(p);
    int i,j,k;//k:匹配串下标,j:模式串下标
    for(k=0;k<m;k++){
        j = 0;
        i = k;
        while(j<n){
            if(p[j]==t[i]){
                i++;
                j++;
            }else{
                break;
            }
        }
        if(j==n){
            printf("在%d处匹配\n",k);
            break;
        }
    }
}

KMP算法是这中算法的改进,在于不是i不是每次都移动一个位置,而是尽可能多的向后移动从而提高匹配效率。到底移动多少个位置,这就是KMP算法的关键。KMP算法维护了一个和模式串长度相同的数组,这个数组表示当前匹配到底最大前缀长度。比如abacab的最大前缀长度就是2,分别是前缀ab,后缀ab。而数组next就是[0,0,1,0,1,2],可以利用这个信息直接跳过已经匹配到的前缀。

二.算法实现

void makeNext(char p[],int next[]){
    int q,k;//k是最大前缀长度,q是匹配串下标
    next[0] = 0;
    for(q=1,k=0;q<strlen(p);q++){
        //若果不相等,那么就从上一次个字符串最长前缀处查看,依次类推
        while(k>0&&p[q]!=p[k]){
            k = next[k-1];
        }
        if(p[q]==p[k]){
            k++;
        }
        next[q] = k;
    }
}
void kmp(char t[],char p[]){
    int next[3] = {0};
    makeNext(p,next);
    int i=0,j=0;//i是匹配串的下标,j是模式串的下标
    while(i<strlen(t)&&j<strlen(p)){
        //如果相等就继续比较
        if(j==0||p[j]==t[i]){
            i++;
            j++;
        }else{//不相等就要跳跃
            j = next[j-1];
        }
    }
    if(j>=strlen(p)){
        printf("模式串匹配在%d处\n",i-j);
    }else{
        printf("匹配失败了");
    }
}
时间: 2024-10-14 19:44:49

字符串查找KMP算法的相关文章

字符串查找KMP算法(转)

如果你用过ctrl+F这个快捷键,那么你有很大的概率使用过这个算法,这就是在待查找字符串(可能有成千上万个字符)中找出模式串(比较小,可能有几个字符),可能找到大于或者等于1次的位置.例如,在ababcd中找出abc.这里介绍算法思想,只给出了第一次出现的位置. 一.算法思想 传统算法是从匹配串第一字符开始和模式串比较,直到遇到不符合的字符,然后从匹配串的下一个字符开始,重复上面的过程.代码如下: void find(char t[],char p[]){ int m = strlen(t);

字符串的KMP算法替换

1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 6 7 class myString 8 { 9 private: 10 string mainstr; 11 int size; 12 void GetNext(string p,int next[]); 13 int KMPFind(string p,int next[]); 14 public: 15 myString(); 16 //~myS

字符串匹配算法KMP算法

数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多多余的不符合的匹配做了冗余的比较.假设源字符串长n,字串长m 该算法最差时间复杂度为 m*(n-m+1),记为O(n*m);这里不做过多解释朴素匹配算法. KMP算法: kmp算法不是在源字符串中下手,他是从字串下手,比如我要在源字符串(acabaabaabcacaabc)中匹配一个字符串字串(ab

查找字符串的 KMP 算法

查找字符串是我们平常编程过程中经常遇到的,现在介绍一种查找字符串算法,增加程序的执行速度. 通常我们是这么写的: /* content: search a string in a othor string author: lw date: 2015-01-30 target: kmp algorithm */ #include <stdio.h> #include <string.h> void compare(char * sourcestr, char * targetstr)

字符串模式匹配KMP算法中的next数组算法及C++实现

一.问题描述: 对于两个字符串S.T,找到T在S中第一次出现的起始位置,若T未在S中出现,则返回-1. 二.输入描述: 两个字符串S.T. 三.输出描述: 字符串T在S中第一次出现的起始位置,若未出现,则返回-1. 四.输入例子: ababaababcbababc 五.输出例子: 5 六.KMP算法解析: KMP算法分为两步,第一步是计算next数组,第二步是根据next数组通过较节省的方式回溯来比较两个字符串. 网络上不同文章关于next数组的角标含义略有差别,这里取参考文献中王红梅<数据结构

字符串匹配算法——KMP算法

1.字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth(<计算机程序设计艺术>的作者). 2.KMP算法 这个算法不太容易理解,网上有很多解释,但

字符串匹配算法-kmp算法

一原理: 部分转自:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发

匹配字符串的KMP算法

其中next序列,表示子串的前后缀最大匹配长度. 例如对于字符串C[], next[i]表示子串c[0 .. i]中, 前缀与后缀的最大匹配长度. 举例如果子串是 abcuab, 其前缀是a, ab, abc, abcu, abcua, 后缀是 b, ab, uab, cuab, bcuab, 其中匹配的最大子串是ab, 长度是2. 按定义挨个计算next的值 public static int[] getNexts(char[] tt) { int[] nexts = new int[tt.l

HDU-1358 Period 字符串问题 KMP算法 求最小循环节

题目链接:https://cn.vjudge.net/problem/HDU-1358 题意 给一个字符串,对下标大于2的元素,问有几个最小循环节 思路 对每个元素求一下minloop,模一下就好 提交过程 TLE maxn没给够 AC 代码 #include <cstring> #include <cstdio> const int maxm=1e6+20; char P[maxm]; int fail[maxm]; void getFail(int m){ fail[0]=fa