KMP算法


一、KMP算法

KMP算法(The Knuth-Morris-Pratt Algorithm),即一种字符串匹配算法。
简单来说,普通的匹配步骤与KMP的差别:

普通匹配

  1. 从第一个模式串的字符开始匹配,比对主串的第一个字符
    1
  2. 如果第一个字符一样,则比对下一个字符,以此类推
    2
  3. 字符出现不匹配
    3
  4. 普通匹配(模式串与每个主串字符都尝试匹配一次):
    4
    KMP算法(以某种规律判定第2个字符肯定不符合,直接跳到对比第3个字符):
    5

二、算法PMT公式

对于上述的KMP匹配中的规律,即是PMT (部分匹配表 Partial Match Table) 计算出的Next数组,该数组表示下一个比较的主串字符移动的位置。
如何计算PMT?
6
PMT的值是模式串的前缀集合与后缀集合的交集中最长元素的长度。
我们可以发现abad按照索引可以分为{a, ab, aba, abad}四个子串,其中前缀和后缀都不包含自身,即:

a 的前缀={null}, 后缀={null}, 无交集, PMT值=0;

ab 的前缀={a}, 后缀={b}, 无交集, PMT值=0;

aba 的前缀={a, ab}, 后缀={ba,a}, 交集={a}, PMT值=1;

abad的前缀={a, ab, aba}, 后缀={bad, ad, d}, 无交集, PMT值=0

因此 PMT={0, 0, 1, 0}.
索引通常是0开始,为了方便处理,在此右移一位使得PMT={-1, 0, 0, 1}.
自比较
简单的可以理解为:
移动位置图

三、 算法代码

//规律:
int[] GetNext(string strPattern)
{
    int[] next = new int[strPattern.Length+1];//NEXT数组
    int i = 0;//索引
    int j = -1;//即使前缀索引又是匹配字符的数量

    while(i<strPattern.Length)
    {
        if (j == -1 || strPattern[i] == strPattern[j])
        {
            i++;
            j++;
            next[i] = j;
        }
        else
            j = next[j];
    }
    return next;
}

int KMP(string strMain, string strMatch,int[] next)
{
    int i = 0;//strMain index
    int j = 0;//strMatch index
    while(i<strMain.Length && j < strMatch.Length)
    {
        if(j==-1 || strMain[i]== strMatch[j])
        {
            i++;
            j++;
        }
        else
        {
            j = next[j];
        }
    }
    //全长匹配
    if (j == strMatch.Length)
        return i - j;//最后匹配索引-长度=首位匹配索引
    else
        return -1;
}

四、 总结

以上是关于KMP算法的内容,个人浅尝辄止,仅供参考。


版权声明:本文为gehong3641原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>