mirror of
https://github.com/kangjianwei/Data-Structure.git
synced 2026-02-08 17:51:45 +08:00
107 lines
2.5 KiB
C
107 lines
2.5 KiB
C
/*=======================
|
||
* KMP算法
|
||
*
|
||
* 包含算法: 4.6、4.7、4.8
|
||
========================*/
|
||
|
||
#include "KMP.h" //**▲04 串**//
|
||
|
||
/*
|
||
* ████████ 算法4.6 ████████
|
||
*
|
||
* 查找
|
||
*
|
||
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
|
||
* 如果查找成功,返回匹配的位置。
|
||
*
|
||
*【注】
|
||
* 1.该实现用到了KMP算法,是一种比较高效的字符串匹配方式
|
||
* 2.教材中没有next参数
|
||
*/
|
||
int Index_KMP(SString S, SString T, int pos, int next[]) {
|
||
int i = pos;
|
||
int j = 1;
|
||
|
||
if(pos < 1) {
|
||
return 0;
|
||
}
|
||
|
||
// 比较字符串
|
||
while(i <= S[0] && j <= T[0]) {
|
||
/*
|
||
* 两种情形:
|
||
* 1.在模式串的第一个字符处就失配
|
||
* 2.主串和模式串处的字符相等
|
||
*/
|
||
if(j == 0 || S[i] == T[j]) {
|
||
i++;
|
||
j++;
|
||
} else {
|
||
// 失配时回到前一个适当的位置
|
||
j = next[j];
|
||
}
|
||
}
|
||
|
||
if(j > T[0]) {
|
||
// 匹配成功,返回匹配位置
|
||
return i - T[0];
|
||
} else {
|
||
// 匹配失败
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ████████ 算法4.7 ████████
|
||
*
|
||
* 计算模式串的“失配数组”,用于KMP算法。
|
||
*/
|
||
void get_next(SString T, int next[]) {
|
||
int i = 1;
|
||
int j = 0;
|
||
|
||
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
|
||
next[1] = 0;
|
||
|
||
// 遍历模式串上的字符
|
||
while(i < T[0]) {
|
||
if(j == 0 || T[i] == T[j]) {
|
||
i++;
|
||
j++;
|
||
next[i] = j;
|
||
} else {
|
||
j = next[j];
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ████████ 算法4.8 ████████
|
||
*
|
||
* 计算模式串的“失配数组”,用于KMP算法。
|
||
* 这是一个优化后的版本,效率较算法4.7有所提高。
|
||
*/
|
||
void get_nextval(SString T, int nextval[]) {
|
||
int i = 1;
|
||
int j = 0;
|
||
|
||
// 模式串第一个字符处失配时,模式串需要从头比较,主串需要前进到下一个位置比较
|
||
nextval[1] = 0;
|
||
|
||
// 遍历模式串上的字符
|
||
while(i < T[0]) {
|
||
if(j==0 || T[i] == T[j]) {
|
||
i++;
|
||
j++;
|
||
|
||
if(T[i] != T[j]) {
|
||
nextval[i] = j;
|
||
} else {
|
||
nextval[i] = nextval[j];
|
||
}
|
||
} else {
|
||
j = nextval[j];
|
||
}
|
||
}
|
||
}
|