KMP算法解析

1.算法解决问题描述

       字符串匹配问题,即在长的字符串序列中去匹配短的字符串。

2.算法解析

       简单的字符串匹配是通过对匹配字符串平移一位,进行逐个比较。这样的话算法复杂度达到o(n*m).

KMP算法是首先得出匹配字符串的特征,这样当两个不匹配时,不用只是平移一位了。极大的减少

复杂度。它可以达到o(n+m)

KMP算法主要的是求覆盖函数(overlay_function)-——匹配字符串本身的特征

比如字符串:abaabcaba

子串
a-1
ab-1
aba0
abaa0
abaab1
abaabc-1
abaabca0
abaabcab1
abaabcaba2

-1表示没有覆盖。

假如覆盖函数的值为k,则满足:a0a1...ak=aj-k...aj

可以采用递归的方法求覆盖函数。对pattern的前j+1序列字符,则有以下可能:

(1) patter[k+1]==pattern[j+1] 此时overlay(j+1)=k+1=overlay(j)+1;

(2)pattern[k+1]!=pattern[j+1] 此时只能在pattern的前k+1个子字符中找,h=overlay(k),如果pattern[h+1] == pattern[j+1]

    则overlay(j+1)=h+1;否则重复(2)过程。

<span style="font-size:14px;">void compute_overlay(const string& pattern)
{
     const int pattern_length = pattern.size();
     int *overlay_function = new int[pattern_length];
     int index;
     overlay_function[0] = -1;
     for(int i=1;i<pattern_length;++i)
      {
           index = overlay_function[i-1];
           while(index>=0 && pattern[i]!=pattern[index+1])
           {
               index = overlay_function[index];
           }
          if(pattern[i]==pattern[index+1])
           {
               overlay_function[i] = index + 1;
           }
           else
            {
                 overlay_function[i] = -1;
             }
          }
         for(i=0;i<pattern_length;++i)
        {
            cout<<overlay_function[i]<<endl;
         }
       delete[] overlay_function;
}</span>

KMP算法是:当发生在j长度不匹配时,只要把pattern向右移动 j-overlay(j) 长度就可以了。

<span style="font-size:14px;">int kmp_find(const string& target,const string& patter)
{
  const int target_length = target.size();
  const int pattern_length = pattern.size();
  int * overlay_value = new int[pattern_length];
  overlay_value[0] = -1;
  int index = 0;
  for(int i=1;i<pattern_length;++i)
   {
       index = overlay_value[i-1];
       while(index>=0 && pattern[index+1]!=pattern[i])
       {
                index = overlay_value[index];
        } 
       if(pattern[index+1]==pattern[i])
        {
           overlay_value[i] = index +1;
        }
        else
        {
             overlay_value[i] = -1;
         }
   }
//match algorithm start
    int pattern_index = 0;
    int target_index = 0;
    while(pattern_index<pattern_length&&target_index<target_length)
   {
        if(target[target_index]==pattern[pattern_index])
       {
            ++target_index;
             ++pattern_index;
        }
       else if(pattern_index==0)
       {
           ++target_index;
       }
       else
       {
            pattern_index = overlay_value[pattern_index-1]+1;
        }
   }
    if(pattern_index==pattern_length)
    {
          return target_index-pattern_index;
     }
     else
     {
          return -1;
       }
       delete [] overlay_value;
}</span>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值