[算法][笔记]KMP详解-模拟

/*
    实现效果:输出每一个能在父串中找到的子串的匹配起始下标
    eg:
        输入:
            son:aba
            parent:ababa


        输出:
            0 2(下标从0开始匹配aba,从2开始匹配aba)
*/

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10,M = 1e6 + 10;

int sonLength,parentLength;//子串长度,父串长度
int Next[N];//Next数组
char son[M],parent[N];//子串,父串

int main()
{
    //依次输入子串长度,子串,父串长度,父串
    //注意:下标从1开始输入,略过0
    cin >> sonLength >> son + 1 >> parentLength >> parent + 1;//son[1] = a,par[1] = a
    //开始匹配,给Next数组赋值
    for(int i = 2,j = 0;i <= sonLength;i++){//遍历子串

        while(j && son[i] != son[j + 1])j = Next[j];//元素不同,Next指针回退

        if(son[i] == son[j + 1])j ++;//遇到相同元素,Next指针后移

        Next[i] = j;//给定每一个子串字符赋予Next值
    }
    /*
        模拟过程:以aba,ababa举例
            1.  j = 0,i = 2,判断while,j不存在,直接略过while,
                此时判断son[2]与son[1]不相同,Next[2] = 0
            2.  j = 0,i = 3,判断while,同理略过while,
                判断son[3]与son[1]相等,j = 1,Next[3] = 1;
            3.  i已经达到3,for循环结束
        //该部分只对子串部分进行判断,并生成Next数组,不涉及父串

    */

    for(int i = 1,j = 0;i <= parentLength;i++){

        while(j && parent[i] != son[j + 1])j = Next[j];//Next指针回退

        if(parent[i] == son[j + 1])j ++;//确定匹配就匹配下一个,即j + 1

        if(j == sonLength){//在父串中找到子串
            printf("%d ",i - sonLength);//子串起始下标
            j = Next[j];//指针回退,准备下一次匹配
        }
    }

    /*
        模拟过程: 父串ababa 子串aba
            1.  i = 1,j = 0,j = 0,略过while,parent[1]:a与son[1]: a匹配,相等,
                j = 1,j != 3
            2.  i = 2,j = 1,parent[2]:b,son[2]:b,相等,略过while,
                parent[2]:b,son[2]:b,j = 2,j != 3
            3.  i = 3,j = 2,parent[3]:a,son[3]:a,相等,略过while,
                j = 3等于sonLength,输出起始下标3 - 3 = 0,j = Next[3] = 1
            4.  i = 4,j = 1,parent[4]:b与son[2]:b相等,j = 2 != 3

            5.  i = 5,j = 2,parent[5]:a与son[3]:a相等,略过while,
                j = 3等于sonLength,输出起始下标5 - 3 = 2,j = Next[3] = 1
            6.  i已到达6,停止for。
    */
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值