0
点赞
收藏
分享

微信扫一扫

【C#】KPM算法解决字符串匹配问题


KPM算法解决字符串匹配问题

  • ​​什么是KPM算法​​
  • ​​步骤​​
  • ​​Ⅰ根据《最大长度表》部分匹配表(next)​​
  • ​​寻找最长前缀后缀​​
  • ​​Ⅱ 根据 部分匹配表 进行匹配​​
  • ​​代码实现​​

什么是KPM算法

  Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。

  KMP方法算法就利用之前判断过信息,通过一个next数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间。

  • KPM的使用场景:模式串在文本串是否出现过,如果出现过,最早出现的位置

步骤

Ⅰ根据《最大长度表》部分匹配表(next)

寻找最长前缀后缀

  • 如果给定的模式串是:“ABCDABD”,从左至右遍历整个模式串,其各个子串的前缀后缀分别如下表格所示:

Ⅱ 根据 部分匹配表 进行匹配

代码实现

字符串匹配问题:
有一个字符串 str1=““上海自来水来自海上””,和一个子串 str2=“自来水”。
现在要判断str1是否含有str2, 如果存在,就返回第一次出现的位置, 如果没有,则返回-1

static void Main(string[] args)
{
string str1 = "上海自来水来自海上";
string str2 = "自来水";

// 得出 部分匹配表
int[] next = KPMNext(str2);
// 根据 得出的 部分匹配表的 next 数组进行匹配,
int index = KPMSearch(str1, str2, next);

Console.WriteLine(index);
}

/// <summary>
/// 获取一个字符串的部分匹配值表
/// </summary>
/// <param name="dest"></param>
/// <returns></returns>
static int[] KPMNext(string dest)
{
// 初始化 数组大小
int[] next = new int[dest.Length];
// 字符串长度为1,部分匹配值就为0
next[0] = 0;
for (int i = 1, j = 0; i < dest.Length; i++)
{
while (j > 0 && dest[i] != dest[j])
{
j = next[j - 1];
}
if (dest[i] == dest[j])
{
j++;
}
next[i] = j;
}
return next;
}

/// <summary>
/// kmp搜索
/// </summary>
/// <param name="str1">源字符串</param>
/// <param name="str2">子字符串</param>
/// <param name="next">部分匹配表</param>
/// <returns></returns>
static int KPMSearch(string str1, string str2, int[] next)
{
for (int i = 0, j = 0; i < str1.Length; i++)
{
while (j > 0 && str1[i] != str2[j])
{
j = next[j - 1];
}

if (str1[i] == str2[j])
{
j++;
}

if (j == str2.Length)
{
return i - j + 1;
}
}
return -1;
}




举报

相关推荐

0 条评论