2023年11月第三周总结

KMP算法

字符串查找算法中的经典算法,时间复杂度O(N + M),N是主串的长度,M是字串的长度。

int* get_next(char s[], int len) {
    int* next = (int*)malloc(sizeof(int) * len);//netx数组的长度跟s2的长度一样

    for (int i = 0; i < len; i ++) {//求每一个位置的next数组的值
        if (i == 0) {//下标0位置规定是-1
            next[i] = -1;
        }
        else if (i == 1) {//下标1位置一定是1
            next[i] = 0;
        }
        else if (i == 2) {//下标2位置,就看下标0位置和下标1位置是不是相等的
            next[i] = s[0] == s[1]? 1: 0;
        }
        else {//其他位置
            int pre = i - 1;//要求位置的前一个位置,只跟要求的前一个位置有关
            int k = next[pre];//要看的位置

            while(k >= 0 && s[k] != s[pre]) {//如果没有看完整个字符串并且看的位置的字符和前一个位置的字符不匹配
                k = next[k];//去下一个位置,因为要最大的前缀和后缀
            }
            next[i] = k + 1;//最后的答案就是k + 1,因为k = next[k],所以当k = -1时也成立
        }
    }
    
    return next;//返回next数组
}

int kmp(char s1[], char s2[])
{
    int s1_len = strlen(s1);//计算需要匹配的字符串的长度
    int s2_len = strlen(s2);//计算字串的长度

    if (s2_len > s1_len) {//如果字串的长度大于要匹配的字符串的长度
        return -1;//直接返回-1,因为不可能匹配
    }

    int* next = get_next(s2, s2_len);//得到next数组

    int x = 0;//在s1中对比的位置
    int y = 0;//在s2中对比的位置

    while(x < s1_len && y < s2_len) {//如果位置都没有越界
        if (s1[x] == s2[y]) {//如果对比的位置匹配
            x ++;//去下一个位置
            y ++;//去下一个位置
        }
        else if (next[y] == -1) {//如果next[y] = -1代表以x开始匹配不出s2字符串了,所以去看s1中下一个位置
            x ++;
        }
        else {//如果在s1中的x位置还可以匹配出s2来,就去看next[y]的位置继续匹配
            y = next[y];
        }
    }

    return y == s2_len? x - s2_len: -1;//如果是s2越界代表找到了,返回x - s2的位置,没有越界代表是s1越界了, 代表没有找到返回-1
}

int strStr(char* haystack, char* needle) {
    return kmp(haystack, needle);
}

next数组也可以求字符串结束位置的next中的值,也就是看整个字符串,这个也是一样的,只是这个题目不用

posted @   lwj1239  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示