把next数组求出来
举个例子
所以我们很容易得出子串每个位置对应的next比对内容
(注意:若为i匹配不上,下一个匹配的是next[i-1],也就是i-1的数字对应的前后缀)
“” 当第一个字符不匹配,我们默认为-1(也可以是0,只是差一个数字罢了)
a,公共前后缀是他自身,往后移动 1 - 0 = 1步,光标移动到a上 为 0
ab, 公共前后缀只有2(本身),所以我们可以认为没有公共前后缀,移动的大小为 2 - 0 = 2步,在程序上就是把比对的光标移到a上 为 0
abc 同上,移动 3 - 0 = 3,把光标移动到a上 0
abca 前后缀最大为1(把等于本身的去掉),所以移动 4 - 1 = 3步,把光标移动到b 1
abcab 前后缀最大为2,所以移动 5 - 2 = 3步,把光标移动到c 2
abcabc 前后缀最大为 3,移动 6 - 3 = 3 步,光标移动到c
于是我们得到如下表格
、
得到next数组代码
int getIn(string a, string b)
{
int bl = b.length();
//获取next数组部分
int i = 0, j = -1;
int* next = new int[b.length() + 10];
memset(next, 0 ,sizeof(next));
next[0] = -1;
while(i < b.length())
{
if(j == -1 || b[i] == b[j])
{
i++;j++;
next[i] = j;
}
else
{
j = next[j];//下标变回0,也就把前面所有部分都移动
}
}
}
找寻KMP匹配的代码
int firIn(string a, string b, int* next)
{
int i = 0, j = 0;
int al = a.length(), bl = b.length();
while(i < al && j < bl)
{
if(j == -1 || a[i] == b[j])
{
i++;j++;
}
else
j = next[j];
//短串右移等于长串左移,相对运动
}
if(j >= bl)
return i - bl;
else return -1;
}
代码
#include#include using namespace std; int main() { string a,b; cin >> a >> b; //获取next数组部分 int j = 0, k = -1; int al = a.length(); int bl = b.length(); int* next = new int[bl + 10]; memset(next, 0 ,sizeof(next)); next[0] = -1; while(j < bl) { if(k == -1 || b[j] == b[k]) { j++;k++; next[j] = k; } else { k = next[k];//变回0 } } //找寻字符串部分 int i = 0; j = 0; while(i < al && j < bl) { if(j == -1 || a[i] == b[j]) { i++;j++; } else j = next[j]; } //cout if(j >= bl) cout << i - bl << endl; else cout << "-1" << endl; for(i = 0; i < bl; i++) cout << next[i] << ((i == bl - 1) ? "" : " ");// cout << endl; }



