zoukankan      html  css  js  c++  java
  • 模式串 从 0 开始的KMP算法

    
    /**
     *  看了 b站视频 BV1jb411V78H 对KMP有了一点理解,然后我写了这个代码
     *  这个代码和视频里面的有一点不同,字符串是从 0 开始的,而不是从1 开始的
     *  希望能够帮到学习KMP的人
     */
    
    
    #include <stdbool.h>
    #include <malloc.h>
    #include "KMP.h"
    
    // KMP.h 内容
    /*
    #define MAXSIZE (255)
    
    typedef struct {
        char ch[MAXSIZE + 1];
        int length;
    }SString;
    
    void Next(SString const *t);
    extern int *next;
    int IndexOf_KMP(SString const *s, SString const *t);
    */
    
    int *next;      // 计算 next数组
    
    /**
     * 计算 0-based 模式串t的next数组
     * @param t 模式串
     */
    void Next(SString const *t) {
        //  模式串 0 开始
        int length = t->length;
    
        // 分配 next数组 所需要的空间
        next = (int *)malloc(sizeof(int) * length);
        for (int *p = next; p < next + length; p++)
        {
            *p = 0;
        }
    
        for (int i = 0; i < length; i++)
        {
            if (i <= 1)     // 前两个next[i]置为-1
            {
                next[i] = -1;
                continue;
            }
    
            // 执行下面的语句的时候, 一定有 i >= 2
    
    
    
            int maxlen = 0;         // 存储最长公共前后缀的长度
    
            /**
             *  // len 表示前缀或后缀的最大长度, 可取的值是 [1..i-1]      // i 为(模式串或next数组)的访问下标
             *  这里主要是 对 模式串在i位置 求 它的最大公共前后缀的长度
             *  从 1 开始 到 i-1 一个一个去试 
             *  
             */
            for (int len = 1; len < i; len++)
            {
                int val = 0;
                bool flag = false;
    
                for (int j = 0, k = i - len; j < len; j++, k++)
                {
                    if (t->ch[j] == t->ch[k])
                    {
                    }
                    else
                    {
                        flag = true;        // len 长度的公共前后缀匹配失败
                        break;
                    }
                }
    
                if (flag == false)          //  公共前后缀长度为len
                    val = len;
                if (val > maxlen)           // 这个比较不是必须的,因为找公共前后缀的长度的时候, len 从 1 到 i-1
                    maxlen = val;           // maxlen 就是 next[i]的值了
            }
            next[i] = maxlen;
        }
    }
    
    // 调用这个函数之前,一定要调用 Next函数,为模式串构建 next数组
    int IndexOf_KMP(SString const *s, SString const *t)
    {
        // 开始匹配
    
        int i = 0, j = 0;       // i 表示主串的下标, j 表示模式串的下标
        while (i < s->length)
        {
            if (j == -1 || s->ch[i] == t->ch[j])
            {
                i++;
                j++;
            }
            else
            {
                j = next[j];
            }
    
            // 匹配成功
            if (j == t->length)
            {
                return i - t->length;
            }
        }
    
        // 匹配失败
        return -1;
    }
    
    
    
  • 相关阅读:
    ELF静态链接
    linux
    百度图表插件
    秀米(图文编辑)
    Html 助手
    在型原型工具
    AnalyticDB
    H5 (webApi) 接口帮助文档
    H5 拖拽读取文件和文件夹
    mongodb int字段的一个小坑
  • 原文地址:https://www.cnblogs.com/Blithe-Chiang/p/13766368.html
Copyright © 2011-2022 走看看