#include<iostream>
using namespace std;
//注意:本代码使用的字符串结构是字符数组是舍弃ch[0]的位置不用,并且用一个专门的变量来存储字符串长度!
#define MAXLEN 255
typedef struct {
char ch[MAXLEN];
int length;
}SString;
2.字符串的基本操作
1.字符串的长度
int StrLength(SString s) {
return s.length;
}
2.获取主串中的子串
bool SubString(SString& Sub, SString s, 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] = s.ch[i];//因为串字符数组的0下标不存储数据
}
Sub.length = len;
return true;
}
3.字符串的比较
int StrCompate(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];//如果字符串S和T的对应位数值不一样,返回两字符串对应位比较的数值
}
}
return S.length - T.length;//如果字符串S和T的对应位数值一样,比较两字符串长度,并返回
}
3.字符串匹配算法
1.使用基本函数操作实现朴素模式匹配算法
int index(SString S, SString T) {//使用基本函数操作实现朴素模式匹配算法
int i = 1;//用于遍历主串
int n = StrLength(S);
int m = StrLength(T);
SString sub;//用于暂存子串
while (i <= n - m - 1) {//循环的临界条件:i定位在主串的位置截下来的子串长度已不足目标子串的长度m
SubString(sub, S, i, m);
if (StrCompate(sub, T) == 0) {
return i;
}
else {
i++;
}
}
return 0;
}
2.不使用基本函数操作实现朴素模式匹配算法
int Index(SString S, SString T) {//不使用基本函数操作实现朴素模式匹配算法,最坏时间复杂度=O(nm)
int i = 1;//定位主串
int j = 1;//定位模式串
while (i <= S.length && j <= T.length) {/*临界条件
1.i>S.length && j <= T.length 表示没有找到模式串
2.i>S.length && j > T.length 表示找到了模式串*/
if (S.ch[i] == T.ch[j]) {
i++;
j++;
}
else {
j = 1;
i = i - j + 2;/*i是主串中的定位
j是模式串中的定位,但也代表主串中每次要比对的子串中的第j个字符
i-j+1代表要回到该次要比较的子串的头部
则i-j+2代表要回到该次要比较的子串的下一个位置,即开始了新一轮的子串比对*/
}
}
if (j > T.length) {
return i - j + 1; //找到了模式串
//return i-T.length;
}
else {
return 0;//没有找到模式串
}
}
3.KMP算法
/*总括: 字符匹配时,i++,j++
字符(非模式串第一位)不匹配时,j变换位置(变换位置由next数组决定)
字符(模式串第一位)不匹配时,i++,j++*/
int Index_KMP(SString S, SString T, int next[]) {/*next[]数组的内容由模式串来决定
但next数组的0下标都不存储数据,且1下标存储的数据为0*/
int i = 1, j = 1;
while (i <= S.length && j <= T.length) {
if (j == 0 || S.ch[i] == T.ch[j]) {/*此处if判断显示i的移动由两种情况引起:
1.主串跟模式串的字符匹配
2.模式串的第一位的字符与主串字符不匹配
因算法中i++与j++是一体的,故将next数组1下标存储的数据置为0
这样两种情况中都可以同时使i++与j++*/
i++;
j++;
}
else {
j = next[j];/*模式串的字符与next数组的数字一一对应
若第一位字符不匹配时,j=0,使i++*/
}
}
if (j > T.length) {
return i - T.length;
}
else {
return 0;
}
}