KMP算法
KMP算法的关键是利用相同真前后缀的长度来减少搜索的次数,提高效率
未优化版
void GetNext (string P, int next[]) {
int p_len = P.size();
int i = 0;
int j = -1;
next[0] = -1;
while (i < p_len) {
if (j == -1 || P[i] == P[j]) {
i++;
j++;
next[i] = j;
}
else {
j = next[j];
}
}
}
int KMP (string S, string T, int next[]) {
GetNext (T, next);
int s_len = S.size();
int t_len = T.size();
int i = 0;
int j = 0;
while (j < t_len && i < s_len) {
if (j==-1 || S[i] == T[j]) {
i++;
j++;
}
else {
j = next[j];
}
}
if (j == t_len) {
return i - j;
}
else {
return -1;
}
}
优化版
void GetNext (string P, int nextval[]) {
int p_len = P.size();
int i = 0;
int j = -1;
nextval[0] = -1;
while (i < p_len) {
if (j == -1 || P[i] == P[j]) {
i++;
j++;
if (P[i] != P[j]) {
nextval[i] = j;
}
else {
nextval[i] = nextval[j];
}
}
else {
j = nextval[j];
}
}
}
int KMP (string S, string T, int nextval[]) {
GetNext (T, nextval);
int s_len = S.size();
int t_len = T.size();
int i = 0;
int j = 0;
while (j < t_len && i < s_len) {
if (j==-1 || S[i] == T[j]) {
i++;
j++;
}
else {
j = nextval[j];
}
}
if (j == t_len) {
return i - j;
}
else {
return -1;
}
}
扩展KMP算法
void GetNext (char T[], int t_len, int next[]) {
int a = 0, p = 0;
next[0] = t_len;
for(int i = 1; i < t_len; i++) {
if (p <= i || i + next[i - a] >= p) {
if (p <= i) {
p = i;
}
while (p < t_len && T[p] == T[p - i]) {
p++;
}
next[i] = p - i;
a = i;
}
else {
next[i] = next[i - a];
}
}
}
参考文献: