代码
#include<bits/stdc++.h>
using namespace std;
const int N = 50;
int nex[N];
int main()
{
string s, p;
s = "AABAABBABAAA";
p = "AB";
nex[0] = 0;
int i = 0, j = 1;
while(j < p.length())
{
if(p[i] == p[j]) nex[j++] = ++i;
else
{
if(i > 0) i = nex[i-1];
else nex[j++] = 0;
}
}
i = 0, j = 0;
while(j < s.length())
{
if(p[i] == s[j]) i++, j++;
else
{
if(i > 0) i = nex[i-1];
else j++;
}
if(i >= p.length())
{
cout << j - p.length() << " ";
i = nex[i-1];
}
}
注意
- i 为使用nex数组的p串指针。j在计算nex数组中,为p串指针,不回头;在匹配中,为s串指针,不回头。
- i,j所处的位置为即将进行字符匹配的位置。
- i 可以表示已经匹配的数目,这决定了为什么字符匹配成功后要++i而不是i++。
- nex的使用要给出失配的前一个索引,即已配对的序列的最右索引。
- 序号起始为0。因此匹配成功 i = p.length()。
- 继续匹配为什么要用nex[i-1],是为了找长得和尾巴一样且最长的头,因为有可能前面匹配掉的有一部分是下一次匹配的开头部分。如下图所示。
比较
异同 | 计算nex | 匹配 |
---|
异 | 遍历p | 遍历s |
同 | 字符匹配成功(i,j,nex的变化) | i,j变化 |
同 | 普通失败,尝试调整 | 普通失败,尝试调整 |
同 | 完全失败nex,j变化(nex初值为0的话,等同于j变化) | j变化 |
异 | 无 | 匹配成功的后序处理 |