参考王道《2023年数据结构考研复习指导》
#include <iostream>
#define Maxsize 255 // 预定义最大串长为255
// 定长顺序存储方式存储串(ch[0]空着不用,从下标1开始存储元素)
typedef struct {
char ch[Maxsize];
int length; // 串的实际长度
} SString;
// 初始化串
void InitString(SString& S) {
S.length = 0;
}
// 求子串(用Sub返回串S的第pos个字符起长度为len的子串)
bool SubString(SString S, SString& Sub, int pos, int len) {
if (pos + len - 1 > S.length) // 子串范围越界
return false;
for (int i = pos; i < pos + len; ++i) {
Sub.ch[i - pos + 1] = Sub.ch[i];
}
Sub.length = len;
return true;
}
// 比较字符串,若S > T,返回值 > 0;若 S == T,返回值 = 0;若S < T,则返回值 < 0
int StrCompare(SString S, SString T) {
for (int i = 1; i <= S.length && i <= T.length; ++i) {
if (S.ch[i] != T.ch[i])
return S.ch[i] - T.ch[i];
}
// 扫描过的所有字符串都相同,则长度长的串更大
return S.length - T.length;
}
// 简单的模式匹配算法
int Index(SString S, SString T) {
int i = 1, j = 1;
while (i <= S.length && j <= T.length) {
if (S.ch[i] == T.ch[j]) {
++i;
++j;
}
else {
i = i - j + 2; // 指针后退重新开始匹配
j = 1;
}
}
if (j > T.length)
return i - T.length;
else
return 0;
}
// 求模式串T的next数组
void get_next(SString T, int next[]) {
// i为当前求第i个位置的next的值
int i = 1, j = 0;
next[1] = 0;
while (i < T.length) { // 因为next[i + 1] = next[i] + 1
// 每次循环时无需改变j的值,即使执行 j = next[j],画图理解
if (j == 0 || T.ch[i] == T.ch[j]) { // j == 0说明没有相等的前后缀
++i;
++j;
next[i] = j; // 若pi == pj,则next[i + 1] = next[i] + 1;
}
else
j = next[j];
}
}
// 求模式串T的nextval数组
void get_nextval(SString T, int nextval[]) {
int i = 1, j = 0;
nextval[1] = 0;
while (i < T.length) {
if (j == 0 || T.ch[i] == T.ch[j]) {
++i;
++j;
if (T.ch[i] != T.ch[j]) // 即T.ch[i + 1] != T.ch[j + 1]
nextval[i] = j; // 即next[i + 1] = next[i] + 1;
else // 若T.ch[i + 1] == T.ch[j + 1],则需要修正
nextval[i] = nextval[j];
}
else
j = nextval[j];
}
}
// KMP算法
int Index_KMP(SString S, SString T, int next[]) {
int i = 1, j = 1;
while (i <= S.length && j <= T.length) {
if (j == 0 || S.ch[i] == T.ch[j]) {
++i;
++j;
}
else
j = next[j];
}
if (j > T.length) // 匹配成功
return i - T.length;
else
return 0;
}
// 创建字符串
void GetString(SString& S) {
InitString(S);
char ch[Maxsize];
std::cin >> ch;
int i = 0;
while (ch[i] != '\0') {
S.ch[i + 1] = ch[i]; // S.ch[0]空着不用
++i;
}
S.length = i;
}
int main() {
SString S, T;
GetString(S);
GetString(T);
int* next = new int[T.length + 1];
int* nextval = new int[T.length + 1];
get_next(T, next);
get_nextval(T, nextval);
std::cout << Index(S, T) << std::endl;
std::cout << Index_KMP(S, T, next) << std::endl;
std::cout << Index_KMP(S, T, nextval) << std::endl;
delete[] next;
delete[] nextval;
system("pause");
return 0;
}