// // Created by Kim Yang on 2020/8/3. // Copyright (c) Kim Yang All rights reserved. // //顺序存储——静态数组实现方式(定长顺序存储),注意下面实现在数组中存放字符串时,都会舍弃,Str[0],第一个结点的空间,以保证字符下标和数组下标保证一致 #include #include /**定义模块**/ #define MAXLEN 15 //预定义最大串长为15 typedef struct { char ch[MAXLEN];//每个分量存储一个字符 int length; //串的实际长度 } SString; //函数声明 void InitStr(SString &S);//初始化 bool StrAssign(SString &T, char *str, int strLength);//赋值操作 void StrCopy(SString &T, SString S);//复制操作 bool StrEmpty(SString S);//判空 void Concat(SString &T, SString S1, SString S2);//串链操作 bool SubString(SString &Sub, SString S, int pos, int len);//求子串 int StrCompare(SString S, SString T);//比较操作,若S>T,则返回值>0;若S=T,则返回值=0;若S 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; } //比较操作,若S>T,则返回值>0;若S=T,则返回值=0;若S T.length) {//匹配成功 return k; } else { return 0; } } //简单模式匹配——王道教材写法 int Index_Simple_CSKaoYan(SString S, SString T) { int i = 1;//i记录当前主串指针 int j = 1;//j记录模式串指针 while (i <= S.length && j <= T.length) { if (S.ch[i] == T.ch[j]) { ++i; ++j;//继续比较后续字符 } else { i = i - j + 2; //检查下一个字串 j = 1;//重制j的值 } } if (j > T.length) {//匹配成功 return i - T.length; } else { return 0; } } //求模式串T的next数组 void getNext(SString T, int *next) { int i = 1, j = 0; next[1] = 0; while (i < T.length) { if (j == 0 || T.ch[i] == T.ch[j]) { ++i; ++j; //如果pi=pj,则next[j+1]=next[j]+1 next[i] = j; } else { //否则令j=next[j],循环继续 j = next[j]; } } } //KMP1 int Index_KMP(SString S, SString T) { int i = 1, j = 1; int next[T.length + 1]; getNext(T, 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; } //优化next数组 void Get_BetterNext(SString T, int *betterNext) { int i = 1, j = 0; int next[T.length + 1]; getNext(T, next);//先求出next数组 betterNext[1] = 0;//令betterNext[1]=0 for (int j = 2; j <= T.length; ++j) { if (T.ch[next[j]] == T.ch[j]) betterNext[j] = betterNext[next[j]];//这里涉及三个数组的对比,仔细看看 else betterNext[j] = next[j]; } } //KMP1 int Index_KMP1(SString S, SString T,int next[]) { int i = 1, j = 1; // int next[T.length + 1]; // getNext(T, 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; } //清空操作 void ClearStr(SString &S) { S.length = 0; memset(S.ch, '\0', MAXLEN);//用到了一个cstring库中的memset函数 } //销毁操作 //void DestoryString(SString &S) { // //} //基于数组实现的字符串存储会自动销毁,无须单独销毁 /**实现模块**/ /**测试模块**/ void printDs(SString S, char *StrName) { printf("当前%s字符串内容为:", StrName); for (int i = 1; i <= S.length; ++i) { if (S.ch[i] != '\0') printf("%c", S.ch[i]);//注意输出单个字符用的是%c,而%s是输出一个字符串 } printf("\n"); } void testBoolOperate(bool result, char *message, char *success, char *fail) { if (result) { printf("%s%s\n", message, success); } else { printf("%s%s\n", message, fail); } } void testModule() { printf("开始测试!\n"); SString S, T; InitStr(S); InitStr(T); char str1[] = "kim";//使用这种初始化列表进行初始化,最后会数组会多一个结束符'\0' // char str1[] = {'k','i','m'}; // 而这种不会,所以在选择初始化方式的时候尽量做到统一,否则你很有可能因为'\0'而匹配不到子串 char str2[] = "kimYang"; testBoolOperate(StrAssign(S, str1, 3), "赋值操作", "成功啦!", "失败啦!"); printDs(S, "S"); testBoolOperate(StrAssign(T, str2, 7), "赋值操作", "又成功啦!", "失败啦!"); printDs(T, "T"); SString S1; InitStr(S1); StrCopy(S1, S); printDs(S1, "S1"); SString S2; InitStr(S2); Concat(S2, S, T); printDs(S2, "串链结束后S2"); SString S3; InitStr(S3); testBoolOperate(SubString(S3, T, 2, 4), "取子串操作", "成功啦", "失败啦"); printDs(S3, "当前取出的S3"); if (0 == StrCompare(S, S1)) { printf("两字符串一样\n"); } else { printf("两个字符串不一样!\n"); } int n = Index(T, S3); if (0 == n) { printf("主串T中不含子串S3\n"); } else { printf("主串T中含有S3,其下标为:%d\n", n); } int n1 = Index_Simple(T, S3); if (0 == n1) { printf("主串T中不含子串S3\n"); } else { printf("主串T中含有S3,其下标为:%d\n", n1); } int n2 = Index_Simple_CSKaoYan(T, S3); if (0 == n2) { printf("主串T中不含子串S3\n"); } else { printf("主串T中含有S3,其下标为:%d\n", n2); } int n3 = Index_KMP(T, S3); if (0 == n3) { printf("主串T中不含子串S3\n"); } else { printf("主串T中含有S3,其下标为:%d\n", n3); } int betterNext[S3.length+1]; Get_BetterNext(S3,betterNext); int n4=Index_KMP1(T,S3,betterNext); if (0 == n4) { printf("主串T中不含子串S3\n"); } else { printf("主串T中含有S3,其下标为:%d\n", n4); } printf("测试结束!\n"); } /**测试模块**/ int main() { testModule(); return 0; }