KMP算法

来源:互联网 发布:海量数据处理编程 编辑:程序博客网 时间:2024/06/08 00:26

KMP算法

主要是解决对于一个模式串在主串中是否能匹配上的问题。这对于后续检查字符相似度,是简单的入门。

对于匹配字符串的问题,首先想到的是,两者从头开始,然后相同往前跳,不同则,回退至初始点,就是有点回到原点的感觉,毋庸置疑,这样的时间复杂度,非常大,最坏的情况会是,每次都跳模式串尾匹配不上,然后全部重新来过。所以,在这个算法的过程明显发现,当匹配上一段串的时候,而后面出现不一致的时候,前面的是已经能匹配上的,那么会有这样的一个情况,如果这个这个已经匹配上的子串,前后缀相似的话,可以直接把后缀当做模式串的前缀,鉴于宝宝没见过什么具体的例子,所以没有添加什么具体的例子,再次按原来的匹配方式进行匹配。这样就能把对于模式串有大量相同子串的匹配节省时间了。说起来非常抽象,主要是没有什么具体的例子,然而例子的表达式非常单一的,只能靠例子的积累才能一点一点理解

直接给出代码吧!


这里面还用到了动态规划和记忆数组的一些想法,所以就是非常的。。。对于大一就学习数据结构的我们,简直就是草菅人命!


就我目前的理解


动态规划的大致想法就是利用子问题来解决母问题,这个是子问题迭代的想法

然后就是对于这样的一类的子问题,是有边界条件的,这个边界条件能解决所有的最底层的子问题

由于动规常常应用于解决最优问题,所以找出最优子结构是关键,这样迭代下去将能求解最优解,其实还是相当于遍历了一次

所以还是会出现了空间爆掉的情况


#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define TRUE  1
#define FALSE  0
#define OK  1
#define ERROR  0
#define INFEASLBLE  -1
#define OVERFLOW  -2
#define MAXSTRLEN  255  //用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN + 1];   //0号单元存放串的长度


void get_next(SString T, int next[])//next数组里面装的是回退到最大匹配子串的该位,该位,前面的数字都已经匹配上
{
        int i, j;
        i = 1;
        j = 0;
        next[1] = 0;//此处的0只能出现在next[1]处
        while (i < T[0])
        {
                if (j == 0 || T[j] == T[i])
                        {next[i] = j;i++;j++;}
                else
                        j = next[j];
        }
        // 算法4.7
        // 求模式串T的next函数值并存入数组next
        // 请补全代码
}
//说实话,现在的我的代码水平还非常的幼稚
//hehe
int Index_KMP(SString S, SString T, int pos)
{
        // 算法4.6
        // 利用模式串T的next函数求T在主串S中第pos个字符之后的位置
        // KMP算法。请补全代码
        int i = pos;//也就是在pos位置后开始检索,不包括pos
        int j = 1;
        int *p;
        p = (int *)malloc(sizeof(int) * (T[0] + 1));//p[0]不放任何东西,主要是因为对应数位的缘故
        get_next(T, p);
        while (i <= S[0] && j <= T[0])
        {
                if (j == 0 || S[i] == T[j])
                {
                        j++, i++;
                }
                else j = p[j];//回退到的该位置,是重新匹配的位置,就像以前直接回退到头一样
                              //这个位置是最难理解的,就是它直接回退到
        }
        if (j > T[0])
                return i - T[0];
        else
                return 0;
}
int main()
{
        SString T, S;
        int i, j, n;
        char ch;
        int pos;
        scanf("%d", &n); // 指定n对需进行模式匹配的字符串
        ch = getchar();//chear the enter,tab or space;
        for (j = 1; j <= n; j++)
        {
                ch = getchar();
                for ( i = 1; i <= MAXSTRLEN && (ch != '\n'); i++) // 录入主串
                {
                        S[i] = ch;
                        ch = getchar();
                }
                S[0] = i - 1; // S[0]用于存储主串中字符个数
                ch = getchar();//这种写法也非常常见,因为这样可以直接跳过\n跳过的情况
                for ( i = 1; i <= MAXSTRLEN && (ch != '\n'); i++) // 录入模式串
                {
                        T[i] = ch;
                        ch = getchar();
                }
                T[0] = i - 1; // T[0]用于存储模式串中字符个数
                pos = Index_KMP(S, T, 0); // 请填空
                printf("%d\n", pos);
        }
        return 0;
}

原创粉丝点击