数据结构字符串匹配——KMP算法

传统的字符串匹配

1.思路:

重头开始,依次将主串与次串相比较。如果相同则比较主串与次串的下一个字符;如果不同,则回溯至之前主串比较的后一个字符,再与次串进行一对一比较,直至主串比完。

2.代码实现:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    char name1[100] = {"abababdcd"};
    char name2[100] = {"ababd"};
    int len1 = strlen(name1);
    int len2 = strlen(name2);
    int ding1 = 0;
    int ding2 = 0;
    while(ding1 < len1 && ding2 < len2){
        if(name1[ding1] == name2[ding2]){
            ++ding1;
            ++ding2;
        }else{
            ding1 = ding1-ding2+1;
            ding2 = 0;
        }
    }
    if(ding2 == len2){
        printf("YES\n");
    }else printf("NO\n");
    return 0;
}

模式匹配的改进算法——KMP

1.思路:

在模式匹配中,我们是在匹配到不相同时,回溯到了之前开始匹配的后一位,然后再次进行匹配,时间复杂度能达到0(m*n),这其中我们做了很多的重复操作,在我们比较后,如果不匹配,我们之前比较过的字符没有被利用,在下次比较中又会比较一次,而KMP算法就是优化了这一过程,利用好已经得到的“部分匹配”使子串尽可能的向右移。而在右移后当前的主串字符就能直接和子串的某一位进行比较(也就是对于主串来说就没有回溯了)。


在模式匹配里,‘a’与'd'不匹配后,子串后移一位,又从'b'开始比较。

主串abababdcb
子串ababd    


主串abababdcb
子串 a       


而实际上,我们知道“abab”这一段我们是已经比较过的,我们通过这一段的比较能很容易得出子串可后移的到的位置


主串abababdcb
子串  ab     


对于“abab”来说,“ab”是它的最长的“以开头为起始的字符串”与“以末尾为终止的字符串”相等的字符串(不包括本身)。如在“aba”中就为“a”,长度为1;在“abac”中没有,长度为0;在“abcab”中为“ab”长度为2。

当我们找到了这样的字符串后,我们就能在满足不找漏的同时将子串向右移动最大的距离,因为我们找的就是最长的相同字符串,下一个子串和主串一一对应的地方一定在这。

这样我们先把子串在不同长度下的最长相同字符串(头,尾)找出,再进行一次对主串的遍历就可以了。



2.代码实现:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

char name1[10] = {"abababdcd"};
char name2[10] = {"ababd"};
int len1 = strlen(name1);
int len2 = strlen(name2);
int ding1 = 0;
int ding2 = 0;

int next[10];//我们用next数组来存储不匹配时,当前字符应该对应的子串的位置。

void GetNext()
{
    int i = 0;
    int k = -1;
    next[0] = -1;
    while(i < len2){
        if((k == -1) || (name2[i]==name2[k]))
            next[++i] = ++k;
        else
            k = next[k];
    }
}

int main()
{
    GetNext();

    while(ding2 < len2){
        while(ding2 != -1 && name1[ding1] != name2[ding2]){
            ding2 = next[ding2];
        }
        ding1++;
        ding2++;
    }

    if(ding2 == len2){
        printf("YES\n");
    }else printf("NO\n");
    return 0;
}



 

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页