kmp算法的定义可以从网上查找。我个人的理解是要从模式串中寻找出和模式串开头字母相同的字母个数,构建一个next数组用于匹配原串失败时判断模式串回溯的位置。
注意点:匹配成功后模式串的迭代因子j应该如何变化?是从0开始还是取最后一个字母的前缀后缀值(考虑到AAA/AAAAAA这样的模式串/原串)。我的方式是在构建next数组时多加一位用于存储模式串最后一个字母的前缀后缀值。网上能找到的代码都是next数组长度与模式串的长度一样。添加多一位的好处是模式串匹配成功后原串的迭代因子不用后退。
以下是源代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace TestOJ
{
public class AplusB
{
static void Main()
{
var line = Console.ReadLine();
var times = int.Parse(line);
for (int i = 0; i < times; i++)
{
var match = Console.ReadLine();
var words = Console.ReadLine();
var t = KMPMatch(words, match); Console.WriteLine(t);
}
} public static int KMPMatch(string input, string match)
{
int[] nextAry = new int[match.Length + 1];
nextAry[0] = -1;
for (int i = 1; i < match.Length; i++)
{
var k = nextAry[i];
if (match[i] == match[k])
{
nextAry[i + 1] = k + 1;
}
}
int j = 0;
int ans = 0;
var len = input.Length;
var n = match.Length;
for (int i = 0; i < len; i++)
{
if (input[i] == match[j])
{
j++;
}
else
{
while (j > 0)
{
j = nextAry[j];
if (input[i] == match[j])
{
j++;
break;
}
}
}
if (j == n)
{
ans++;
j = nextAry[j];
}
}
return ans;
}
}
}
执行的时间/内存花费是: 164ms/36MB。