- 前缀和后缀的概念(以aabaa为例)
所有的前缀和后缀如下
下面详细说next数组(next[i]表示p[0]-p[i]串的最大相同前后缀长度)的求法,可以看成是一个动态规划的过程。
首先,next[0] = 0(前缀和后缀不能是字符串本身)。
现在要求next[i],首先需要前i个字符的最大相同前后缀长度j(也就是next[i-1]),然后判断p[j](下表中Z)与p[i](下表中Y)是否相同,相同则next[i] = j+1。
字符串如下
若Z!=Y。
那么就要求出最大的j’如上,使得p1前j’个字符和p2后j’个字符完全相同,然后p1==p2,也就是最大的j’使得p1前j’个字符和p1后j’个字符完全相同,那么j’也就是next[j-1]的含义(j’==next[j-1]),因此下一次比较也就是p[j’]与p[i],若相同则next[i] = j’+1,若不相同则p1’和p2’作为新的p1和p2继续进行上述操作,直到j’ = 0,此时若p[0]==p[i]则next[i] = 1,否则next[i] = 0。
下面是代码
#include<iostream>
#include<string>
#include<vector>
using namespace std;
// next数组 next[i]表示p串的相同前后缀最大长度
// next[j-1] 也可以看做是 p[j]和s[i]匹配不上,p下一个需要跳转的字符位置
// 求next数组可以看成是一个动态规划的过程
int main(int argc, char const *argv[])
{
string s = "aabbaabbaabbaafwe";
string p = "aabbaaf";
vector<int> next(p.size(),0);
for (int i = 1;i<p.size();++i){
int j = next[i-1];
while(j>0&&p[i]!=p[j]){
j = next[j-1];
}
if(p[i]==p[j]){//不相等则说明j==0
j++;
}
next[i] = j;
}
i = 0,j = 0;
while(i<s.size()&&j<p.size()){
while(j>0&&p[j]!=s[i]){
j = next[j-1];
}
if (p[j]==s[i]){
j++;
i++;
}
else{//其实也就是j == 0的情况 并且s[i]!=p[0],只有i指针后移。
i++;
}
}
if (j == p.size()) cout<<"match"<<endl;
else cout<<"not match"<<endl;
return 0;
}