using namespace std;
#include <iostream>
#include<string>
//自定义字符串存储结构String(包括char数组、length长度)
#define maxlen 20
typedef struct {
char ch[maxlen];
int length;
}String;
//初始化s
void strInit(String& s) {
s.length = 0;
s.ch[0] = s.length; //ch[0]空着用来存长度,初始化为0
}
//s判空
bool strEmpty(String s) {
if (s.length == 0) //如果长度为0代表空串
return true;
else
return false;
}
//获得s长度
int strLength(String s) {
cout << "长度打印:" << s.length << endl;;
return s.length; //或者s.ch[0]
}
//将string字符串赋值到s数据结构中用char数组保存
String strAssign(String &s, string t) {
int i = 1; //从1开始存字符,0空着用来存长度
s.length =0;
cout << "字符串打印:";
for (int j = 0; j < t.length(); j++) {
s.ch[i] = t[j];
cout << s.ch[i] << " ";
s.length++;
i++;
}
s.ch[0] = s.length; //0空着用来存长度
cout << endl;
return s;
}
/////////上面都是一些基础函数,下面开始KMP算法/////////////////////////////////////////////
//step1:求出子串的next[j]值【普通版】
void get_next(String s, int next[]) {
int j = 1, k = 0;
next[1] = 0; //next[1]值必须填0
while(j<s.length){
if (s.ch[j] == s.ch[k] || k == 0) {
j++;
k++;
next[j] = k;
}
else
k = next[k];
}
//打印看看
cout <<"打印next[i]为: ";
for (int i = 1; i <=s.length; i++)
cout << next[i] << " ";
cout << endl;
}
//step1:求出子串的nextval[j]值【改进版,只记录不相同值的索引,避免j的无效回退。2个方法2选1即可】
void get_nextval(String s, int nextval[]) {
int j = 1, k = 0;
nextval[1] = 0; //nextval[1]值必须填0
while (j < s.length) {
if (s.ch[j] == s.ch[k] || k == 0) {
j++;
k++;
if (s.ch[j] != s.ch[k])
nextval[j] = k;
else
nextval[j] = nextval[k];
}
else
k = nextval[k];
}
//打印看看
cout << "打印nextval[i]为: ";
for (int i = 1; i <= s.length; i++)
cout << nextval[i] << " ";
cout << endl;
}
//step2:开始主串中匹配子串,并返回第一个元素出现的位置
int index3(String s, String t, int next[]) {
int i = 1, j = 1;
while (i <= s.length && j <= t.length) { //找到最后一个字符为止
if (j == 0||s.ch[i] == t.ch[j]) { //如果字符不相同或者j为0了,i和j同步往后移1位
i++;
j++;
}
else
j = next[j]; //j回退到next[j]位置
}//while结束,s和t至少有一个找到头了
if (j > t.length) {
//打印看看
cout << "index3打印子串为: ";
for (int m = i - t.length; m < i; m++)
cout << s.ch[m] << " ";
cout << endl;
return (i - t.length); //或者i-t.length,返回i最开始的位置
}
else
return 0;
}
void main() {
int next[20];
int nextval[20];
string sf = "aaaacabcaaaabab";
string sz = "aaaab";
String ss ,tt;
strInit(ss); //初始化主串
strInit(tt); //初始化子串
strAssign(ss, sf); //把字符串放进数据结构
strAssign(tt, sz); //把字符串放进数据结构
strLength(ss); //获取长度
strLength(tt); //获取长度
get_next(tt, next); //获得子串各个next值
cout << "用next的index3 i下标:" << index3(ss, tt, next) << endl;
get_nextval(tt, nextval); //获得子串各个nextval值
cout << "用nextval的index3 i下标:" << index3(ss, tt, nextval) << endl;
}