KMP字符串匹配理解和c++实现

匹配过程中,若相同,主串和模式串指针各增加1 

若产生失配,则主串指针不变,模式串指针退回到next位置继续匹配,若模式串指针退回到0匹配失配,则主串指针加1,,模式串指针仍为索引为0的字符重新开始匹配

计算模式串的next数组值

next数组值表示:主串中第i个字符与模式串中第j个字符失配时,主串中第i个字符应该与模式串中哪个字符再进行比较,只和模式串有关,和主串无关

 

/*
StrLocation  0 1 2 3 4 5 6 7
Str          a b a a b c a c
BackIndex    -1 0 0 1 1 2 0 2

kmp算法中当主串第j个字符与模式串索引i个字符(索引从0开始)匹配失效时,模式串退回到 Next[i]继续匹配
*/
void GetNext(std::string Str, int Next[])
{
    int StrLocation = 1;
    int BackIndex = 0;
    Next[0] = -1;//作为首字符判断位,如果Next[0] = 0,if条件if (BackIndex == 0 || Str[BackIndex] == Str[StrLocation])判断失效
    Next[1] = 0;
    while (StrLocation < Str.size())
    {
        if (BackIndex == -1 || Str[BackIndex] == Str[StrLocation])
        {
            Next[StrLocation + 1] = BackIndex + 1;
            StrLocation++;
            BackIndex++;
        }
        else
        {
            BackIndex = Next[BackIndex];
        }
    }
}

//Next[0]作为当最长公共前后缀子串只有第一个字符时,即 BackIndex == 0 且  Str[1] != Str[StrLocation]  时的标志,
//Next[0]可以是任何其他非索引范围的整数,但是设为-1的好处是可以合并判断同时加1,
//而不必分开判断将模式串索引位置0
void kmp(const std::string MainStr, const std::string MinorStr)
{
    const int n = MinorStr.size();
    int Next[100];
    GetNext(MinorStr, Next);

    int MainIndex = 0, MinorIndex = 0;

    while (MainIndex < MainStr.size() && MinorIndex < MinorStr.size())
    {
        if (MinorIndex == -1 || MainStr[MainIndex] == MinorStr[MinorIndex])
        {
            MainIndex++;
            MinorIndex++;
        }
        else
        {
            MinorIndex = Next[MinorIndex];
        }
    }
}

在想为什么Next[0] = -1;  如果  Next[0] = 0;只能知道回退到了模式串首字符,但是无法根据 Next[0]的值确定模式串首字符是否匹配,且可能陷入死循环

对比下面的代码

void kmp(const std::string MainStr, const std::string MinorStr)
{
       const int n = MinorStr.size();
       int Next[100];
       GetNext(MinorStr, Next);
       int MainIndex = 0, MinorIndex = 0;
       while (MainIndex < MainStr.size() && MinorIndex < MinorStr.size())
       {
              if (MinorIndex == Next[0] && MainStr[MainIndex] != MinorStr[MinorIndex]) //when Next[0] = 0
              {
                     MainIndex++;
                     MinorIndex = 0;
              }
              else if (MainStr[MainIndex] == MinorStr[MinorIndex])
              {
                     MainIndex++;
                     MinorIndex++;
              }
              else
              {
                     MinorIndex = Next[MinorIndex];
              }
       }
}
void GetNext(std::string Str, int Next[])
{
       int StrLocation = 1;
       int BackIndex = 0;
       Next[0] = 0;
       Next[1] = 0;
       while (StrLocation < Str.size())
       {
              if (BackIndex == 0 && Str[BackIndex] != Str[StrLocation])   //when Next[0] = 0
              {
                     Next[StrLocation + 1] = BackIndex;
                     StrLocation++;
              }
              else if(Str[BackIndex] == Str[StrLocation])
              {
                     Next[StrLocation + 1] = BackIndex + 1;
                     StrLocation++;
                     BackIndex++;
              }
              else
              {
                     BackIndex = Next[BackIndex];
              }
       }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值