匹配的过程是这样的
已知空格与D不匹配时,前面六个字符"ABCDAB"是匹配的。查表可知,最后一个匹配字符B对应的"部分匹配值"为2,因此按照下面的公式算出向后移动的位数:
移动位数 = 已匹配的字符数 - 对应的部分匹配值
因为 6 - 2 等于4,所以将搜索词向后移动4位。
10.
因为空格与C不匹配,搜索词还要继续往后移。这时,已匹配的字符数为2("AB"),对应的"部分匹配值"为0。所以,移动位数 = 2 - 0,结果为 2,于是将搜索词向后移2位。
11.
因为空格与A不匹配,继续后移一位。
12.
逐位比较,直到发现C与D不匹配。于是,移动位数 = 6 - 2,继续将搜索词向后移动4位。
13.
逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。如果还要继续搜索(即找出全部匹配),移动位数 = 7 - 0,再将搜索词向后移动7位,这里就不再重复了。
代码,这里面最主要的是next数组的求法,其中最重要的是又是当求next中两个点数据不一样的时候,该如何计算。
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
void Next(string s, vector<int> &next)
{
int p, k;
next[0] = 0;
for (int p = 1, k = 0; p < s.size(); p++)
{
while (k>0&&s[p] != s[k])//相当于求k+1个和第p个是否匹配,这个匹配就是最大的匹配串了
{
k = next[k - 1];//因为是从0开始索引的,所以s[k]相当于第k+1个
}
if (s[p] == s[k])
{
k++;
}
next[p] = k;
}
}
void kmp(string s1, string s2, vector<int> &next)//s2长串,s1短串
{
int len1 = s1.size();
int len2 = s2.size();
Next(s2,next);
int p1 = 0;
int p2 = 0;
for (; p1 < len1;p1++)//长串搜索结束为止
{
while (p2 > 0 && s2[p2] != s1[p1])//相当于求s2的第p2个和s1的第p1个是否匹配
{
p2 = next[p2 - 1];//前面的next[p2-1]肯定是匹配的
}
if (s2[p2] == s1[p1])
p2++;
if (p2 == len2)
{
cout << "匹配成功" << p1 << endl;
break;
}
}
}
int main()
{
vector<int> next(100, 0);
string s1, s2;
cin >> s1 >> s2;
kmp(s1, s2, next);
system("pause");
return 0;
}