#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 255 //串的最大长度
//动态数组实现(堆分配存储)
typedef struct {
char *ch; // 按串长分配存储区,ch指向串的基地址
int length; // 串的长度
} HString;
//初始化
bool InitHString(HString &S) {
//手动分配一片连续空间,释放需要手动 free
S.ch = (char *) malloc(MAXLEN * sizeof(char));
S.length = 0;
}
//串的链式存储
//实现 1 个结点存储一个字符 存储密度第,每存储一个字符,字符占1
//typedef struct StringNode{
// char ch;//每个结点存储一个字符占1B,指针占4B
// struct StringNode *next;//下一个结点指针
//}StringNode,*String;
//实现2:每个结点存多个字符
typedef struct StringNode {
char ch[4];//每个结点存多个字符
struct StringNode *next;//下一个结点指针
} StringNode, *String;
//静态数组实现(定长顺序存储)
typedef struct {
char ch[MAXLEN]; //每个分量存储一个字符
int length;// 串的长度
} SString;
//判断空串
bool StrEmpty(SString S) {
return S.length == 0;
}
//求串长 返回串S的元素个数
int StrLength(SString S) {
return S.length;
}
//清空串
void ClearString(SString &S) {
S.length = 0;//逻辑上删除
}
//销毁串
void DestroyString(SString &S) {
ClearString(S);
//离开作用域 等待系统自动回收
}
void InitSString(SString &S) {
S.length = 0;
}
//求子串 用 Sub返回 串S的 第 pos 个字符起长度为 len 的子串
//比如 wangdao 获取 gda 的子串
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];
}
Sub.length = len;
return true;
}
//打印串
void PrintSString(SString S) {
for (int i = 1; i <= S.length; ++i) {
printf("%c", S.ch[i]);
}
printf("\n");
}
//比较 S 和 T 两个串的大小 即比较同位置的字符大小,碰见不相同的则比较两个字符大小,比较完成,如果都相同,则长度长的字符串大,如果长度相同,则相同
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;
}
定位操作。若主串 S 中 存在与 串 T 相同的子串,返回它在主串 S 中第一次出现的位置;否则,返回0
使用 SubString 和 StrCompare 实现
//
//int Index(SString S,SString T) {
// int pos = 1, n = StrLength(S), m = StrLength(T);
// SString sub;//用于暂存子串
// InitSString(sub);
// while (pos < n-m + 1) {
// SubString(sub,S,pos,m);
// if(StrCompare(sub,T) !=0) pos++;
// else return pos;//返回子串在主串中的位置
// }
// return 0;
//}
//朴素的模式匹配算法(简单模式匹配算法)
//如果 主串 S 的长度为 n,模式串 T的长度为 m
//最好情况下模式串在主串的最前面,即需要比较 m 次,最好时间复杂度 为O(m)
//最坏情况需要 (n-m+1)*m 次比较,最坏时间复杂度 O((n-m+1)*m
int Index(SString S, SString T) {
//将主串在于模式串长度相同的子串找出,依次与模式串匹配,如果子串与模式串某个字符不相等,则停止匹配,检索下一个子串
int k = 1;
int i = k, j = 1;
while (i <= S.length && j <= T.length) {
if (S.ch[i] == T.ch[j]) {
i++;
j++;//继续比较后面的字符
} else { // 当前子串不匹配
k++;
i = k;
//i = (i-(j-1)) + 1 //模式串回退j-1,主串也回退j-1,同时主串要再+1
j = 1;//模式串
}
}
if (j > T.length) { // 模式串匹配完成
return k;
} else { //主串字符耗尽,而模式串没有匹配完
return 0;
}
}
//前缀:包含第一个字符,但不包含最后一个字符
//后缀:包含最后一个字符,单不包含第一个字符
//最长公共前后缀:即前缀和后缀相同的字符串,不包含当前字符串 即 abcdefg 不是 abcdefg 的公共前后缀
//例 ab :不存在;
// aba:不存在
// aa:a
// abab:ab
//abcdebabcd:abcd
//求next数组,即最长的公共前后缀 +1
void get_next(SString T, int next[]) {
//ababab
int i = 1, j = 0;
next[1] = 0;
while (i < T.length) {
if (j == 0 || T.ch[i] == T.ch[j]) {
++i;
++j;
next[i] = j;
} else {
j = next[j];
}
}
}
//求 nextval数组
void get_nextval(SString T, int next[], int nextval[]) {
nextval[1] = 0;
for (int i = 2; i <= T.length; ++i) {
if (T.ch[next[i]] == T.ch[i]) {//如果当前字符T.ch[i]和当前的 以当前字符对应的 next数组下标的字符 T.ch[next[i]] 相等
nextval[i] = nextval[next[i]];//则当前字符的 nextval[i] = nextval[next[i]]
} else {
nextval[i] = next[i];//否则当前字符 nextval[i] 等于 next[i]
}
}
}
//KMP算法
int Index_KMP(SString S, SString T) {
int i = 1, j = 1;
int next[T.length + 1];
get_next(T, next);//求模式串的 next 数组
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;
}
}
//KMP算法改进 nextval数组
int Index_KMP_nextval(SString S, SString T) {
int i = 1, j = 1;
int next[T.length + 1];
get_next(T, next);//求模式串的 next 数组
int nextval[T.length + 1];
get_nextval(T, next, nextval);
while (i <= S.length && j <= T.length) {
if (j == 0 || S.ch[i] == T.ch[j]) {
i++;
j++;
} else {
j = nextval[j];
}
}
if (j > T.length) {
return i - T.length;//匹配成功
} else {
return 0;
}
}
int main() {
int pos = 0;
int len = 0;
SString S;
InitSString(S);
S.ch[1] = 'w';
S.length++;
S.ch[2] = 'a';
S.length++;
S.ch[3] = 'n';
S.length++;
S.ch[4] = 'g';
S.length++;
S.ch[5] = 'd';
S.length++;
S.ch[6] = 'a';
S.length++;
S.ch[7] = 'o';
S.length++;
printf("打印串S:\n");
PrintSString(S);
SString Sub;
InitSString(Sub);
//求wangdao 的子串 dao
pos = 4, len = 3;
if (SubString(Sub, S, pos, len)) {
printf("获取S子串,pos:%d,len:%d成功\n", pos, len);
printf("打印S的子串Sub:\n");
PrintSString(Sub);
} else {
printf("获取S子串,pos:%d,len:%d失败\n", pos, len);
}
SString T;
InitSString(T);
T.ch[1] = 'w';
T.length++;
T.ch[2] = 'a';
T.length++;
T.ch[3] = 'n';
T.length++;
T.ch[4] = 'g';
T.length++;
T.ch[5] = 'd';
T.length++;
T.ch[6] = 'a';
T.length++;
T.ch[7] = 'a';
T.length++;
printf("打印串T:\n");
PrintSString(T);
int result = StrCompare(S, T);
if (result > 0)
printf("S>T\n");
else if (result == 0)
printf("S=T\n");
else if (result < 0)
printf("S<T\n");
T.ch[1] = 'd';
T.ch[2] = 'a';
T.ch[3] = 'o';
T.length = 3;
T.ch[4] = 'a';
// T.length = 4;
// T.ch[3] ='o';
// T.length = 3;
printf("打印串S:\n");
PrintSString(S);
printf("打印串T:\n");
PrintSString(T);
// pos = Index(S,T);
//pos = Index_KMP(S,T);
pos = Index_KMP_nextval(S, T);
if (pos != 0) {
printf("子串T在主串S中的位置为%d\n", pos);
} else {
printf("子串T不是主串S的子串\n");
}
// T.ch[4] = 'a';
SString T1;
InitSString(T1);
T1.ch[1] = 'G';
T1.ch[2] = 'O';
T1.ch[3] = 'O';
T1.ch[4] = 'G';
T1.ch[5] = 'L';
T1.ch[6] = 'E';
T1.length = 6;
int T1_next[T1.length+1];
get_next(T1,T1_next);
int T1_nextval[T1.length+1];
get_nextval(T1,T1_next,T1_nextval);
printf("\n");
return 0;
}
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交