文字描述:
串,就是字符串的意思。在数据结构中,串的存储方式有三种:定长顺序存储表示、堆分配存储表示和块链存储表示:
定长顺序存储表示: 以一组地址连续的存储单元存放字符序列,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。超出预定义的串值会被舍弃,成为“截断”。
堆分配存储表示: 以一组地址连续的存储单元存放字符序列,但它们的存储空间是在执行时动态分配而得。
块链存储表示: 和线性表的链式存储结构类似,如下图,一个是结点大小为1的链表,一个是结点大小为4的链表;在链式存储方式中,结点大小的选择很重要,太小的话,虽然运算方便但是存储占用量大;如果太大的话,会太浪费空间。另外,它除了连接字串方便外,其他也不如前面两种存储方式灵活,一般都不用。
串的求子串的定位函数:返回子串在主串中的位置。
方法一,通用做法,如下图主串位置在匹配过程中可能会后退
方法二:模式匹配的一种改进算法KMP。主串匹配的下标一直前进,没有后退。关于这个算法,虽然KMP实现的代码很短,还是并不容易理解,可以参考下https://www.cnblogs.com/ZuoAndFutureGirl/p/9028287.html
方法三:优化后的KMP。按照方法二的KMP算法,在某些情况下是有缺陷的,比如主串为“aaabaaaab”, 子串为”aaaab”的时候,匹配时,当i=4、j=3时,S.ch[4] != T.ch[4],有next[j]指示还需进行i=4,j=3; i=4,j=2; i=4,j=1这3次比较。显然j=3、2、1都为’a’,和主串中i=4的比较结果都是一样的,可以将模式一气向右滑动4个字读的位置直接进行i=5、j=1的字符比较。
算法分析:
一般方法求子串在主串中的位置下标的时间复杂度为n*m
而KMP算法求子串在主串中的位置下标的时间复杂度为n+m, 另外在KMP中求串的next函数值的算法的时间复杂度为m。
代码实现:
串的定长顺序表示
1 // 2 // Created by Zhenjie Yu on 2019-04-14. 3 // 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #define DEBUG 10 #ifdef DEBUG 11 #include <stdarg.h> 12 #define LOG(args...) _log_(__FILE__, __FUNCTION__, __LINE__, ##args); 13 static void _log_(const char *file, const char *function, int line, const char * format, ...) 14 { 15 char buf[1024] = {0}; 16 va_list list; 17 va_start(list, format); 18 vsprintf(buf+strlen(buf), format, list); 19 sprintf(buf+strlen(buf), "\n"); 20 va_end(list); 21 printf(buf); 22 } 23 #else 24 #define LOG 25 #endif // DEBUG 26 27 #define MAX_STRING 255 28 typedef unsigned char SString[MAX_STRING+1]; //第一位表示串长 29 30 static int Concat(SString T, SString S1, SString S2){ 31 int uncut = -1; 32 if(S1[0]+S2[0] <= MAX_STRING){ 33 snprintf(T+1, S1[0]+1, "%s", S1+1); 34 snprintf(T+1+S1[0], S2[0]+1, "%s", S2+1); 35 T[0] = S1[0] + S2[0]; 36 uncut = 1; 37 }else if(S1[0] < MAX_STRING){ 38 snprintf(T+1, S1[0]+1, "%s", S1+1); 39 snprintf(T+1+S1[0], MAX_STRING-S1[0]+1, "%s", S2+1); 40 T[0] = MAX_STRING; 41 uncut = 0; 42 }else{ 43 snprintf(T+1, MAX_STRING+1, "%s", S1+1); 44 T[0] = MAX_STRING; 45 uncut = 0; 46 } 47 return uncut; 48 } 49 50 static int StrAssign(SString T, const char chars[]){ 51 memset(T, 0, MAX_STRING+1); 52 int len = strlen(chars); 53 if(len > MAX_STRING){ 54 return -1; 55 } 56 T[0] = len; 57 snprintf(T+1, len+1, "%s", chars); 58 return 0; 59 } 60 61 static int SubString(SString Sub, SString S, int pos, int len) 62 { 63 if(pos<1 || pos>S[0] || len<0 || len>(S[0]-pos+1)){ 64 return -1; 65 } 66 snprintf(Sub+1, len+1, S+pos); 67 Sub[0] = len; 68 return 0; 69 } 70 71 int main(int argc, char *arg) 72 { 73 SString S1, S2, T, Sub; 74 int ret = -1; 75 76 StrAssign(S1, "test123"); 77 LOG("设置串S1的值为%s, 长度为%d", S1+1, S1[0]); 78 79 StrAssign(S2, "abcdef"); 80 LOG("设置串S2的值为%s, 长度为%d", S2+1, S2[0]); 81 82 ret = Concat(T, S1, S2); 83 LOG("连接串S1和S2,并保存到变量T中,连接后T为%s, T的长度为%d", T+1, T[0]); 84 85 ret = SubString(Sub, T, 4, 6); 86 LOG("求主串T中,起始地址为4,长度为6的子串,子串结果保存咋变量Sub中; Sub的值为%s,长度为%d", Sub+1, Sub[0]); 87 return 0; 88 }
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled 设置串S1的值为test123, 长度为7 设置串S2的值为abcdef, 长度为6 连接串S1和S2,并保存到变量T中,连接后T为test123abcdef, T的长度为13 求主串T中,起始地址为4,长度为6的子串,子串结果保存咋变量Sub中; Sub的值为t123ab,长度为6 Process finished with exit code 0
串的堆分配存储表示及其模式匹配算法
1 // 2 // Created by Zhenjie Yu on 2019-04-14. 3 // 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #define DEBUG 10 #ifdef DEBUG 11 #include <stdarg.h> 12 #define LOG(args...) _log_(__FILE__, __FUNCTION__, __LINE__, ##args); 13 static void _log_(const char *file, const char *function, int line, const char * format, ...) 14 { 15 char buf[1024] = {0}; 16 va_list list; 17 va_start(list, format); 18 vsprintf(buf+strlen(buf), format, list); 19 sprintf(buf+strlen(buf), "\n"); 20 va_end(list); 21 printf(buf); 22 } 23 #else 24 #define LOG 25 #endif // DEBUG 26 27 28 typedef struct HString{ 29 char *ch; //如果是空串,就为NULL;否则按串长分配存储区 30 int length; //串长度 31 }HString; 32 33 //生成一个其值等于串常量chars的串T 34 static int StrAssign(HString *T, const char *chars); 35 //返回S的元素个数,称为串的长度 36 static int StrLength(HString S); 37 //如果S大于T,则返回正值; 如果S等于T,则返回0; 否则返回负值 38 static int StrCompare(HString S, HString T); 39 //将S清为空串 40 static int ClearString(HString *S); 41 //用T返回由S1和S2连接而成的新串 42 static int Concat(HString *T, HString S1, HString S2); 43 //用Sub返回串S的第pos个字符起长度为Len的子串 44 static int SubString(HString *Sub, HString S, int pos, int len); 45 46 //返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0; 47 static int Index(HString S, HString T, int pos){ 48 if(pos<0 || pos>=S.length){ 49 return -1; 50 } 51 int i = pos, j = 0; 52 while(i<S.length && j<T.length){ 53 LOG("普通方法: 比较S.ch[%d]=%c 和 T.ch[%d]=%c", i, S.ch[i], j, T.ch[j]); 54 if(S.ch[i] == T.ch[j]){ 55 i += 1; 56 j += 1; 57 }else{ 58 i = i-j+1; 59 j = 0; 60 LOG("普通方法: 两者不等,需把S的下标i回退到%d, 把T的下标j回退到%d", i, j); 61 } 62 } 63 if(j>=T.length){ 64 return i-T.length; 65 }else{ 66 return 0; 67 } 68 } 69 70 71 72 /*********************使用KMP算法求子串位置的定位函数************************/ 73 void get_next(HString T, int next[]){ 74 int i = 1; 75 int j = 0; 76 memset(next, 0, T.length); 77 next[1] = 0; 78 int count = 1; 79 while(i<T.length){ 80 count += 1; 81 if(j == 0 || T.ch[i-1] == T.ch[j-1]){ 82 ++i; 83 ++j; 84 next[i] = j; 85 }else{ 86 j = next[j]; 87 } 88 } 89 90 for(i=1; i<=T.length; i++){ 91 if(next[i]){ 92 next[i] = next[i]-1; 93 } 94 next[i-1] = next[i]; 95 } 96 97 for(i=0; i<T.length; i++){ 98 LOG("KMP算法中字串(%s)的next函数值: next[%d]=%d", T.ch, i, next[i]); 99 } 100 } 101 //https://www.cnblogs.com/ZuoAndFutureGirl/p/9028287.html 102 static int Index_KMP(HString S, HString T, int pos){ 103 if(pos<0 || pos>=S.length){ 104 return -1; 105 } 106 int i = 0; 107 int j = 0; 108 int *next = (int*)malloc(sizeof(int)*T.length+1); 109 110 get_next(T, next); 111 112 i = pos; 113 j = 0; 114 while(i<S.length && j<T.length){ 115 LOG("用KMP方法: 比较S.ch[%d]=%c 和 T.ch[%d]=%c", i, S.ch[i], j, T.ch[j]); 116 if(S.ch[i] == T.ch[j] || j == 0){ 117 i += 1; 118 j += 1; 119 }else{ 120 j = next[j]; 121 LOG("用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到%d", j); 122 } 123 } 124 125 free(next); 126 if(j>=T.length){ 127 //匹配成都 128 return i-T.length; 129 }else{ 130 return 0; 131 } 132 } 133 134 135 /*********************使用优化后的KMP算法求子串位置的定位函数************************/ 136 void get_next_Val(HString T, int nextval[]) 137 { 138 memset(nextval, 0, T.length+1); 139 int i = 1; 140 int j = 0; 141 nextval[1] = 0; 142 while (i<T.length){ 143 if(j==0 || T.ch[i-1] == T.ch[j-1]){ 144 i += 1; 145 j += 1; 146 if(j && (T.ch[i-1] != T.ch[j-1])){ 147 nextval[i] = j; 148 }else{ 149 nextval[i] = nextval[j]; 150 } 151 }else{ 152 j = nextval[j]; 153 } 154 } 155 156 for(i=1; i<=T.length; i++){ 157 if(nextval[i]){ 158 nextval[i] = nextval[i]-1; 159 } 160 nextval[i-1] = nextval[i]; 161 } 162 163 for(i=0; i<T.length; i++){ 164 LOG("优化后的KMP算法中字串(%s)的nextval函数值: nextval[%d]=%d", T.ch, i, nextval[i]); 165 } 166 return ; 167 } 168 static int Index_KMP_Val(HString S, HString T, int pos) 169 { 170 if(pos<0 || pos>=S.length){ 171 return -1; 172 } 173 int i = 0; 174 int j = 0; 175 int *next = (int*)malloc(sizeof(int)*T.length+1); 176 177 get_next_Val(T, next); 178 179 i = pos; 180 j = 0; 181 while(i<S.length && j<T.length){ 182 LOG("用优化后的KMP方法: 比较S.ch[%d]=%c 和 T.ch[%d]=%c", i, S.ch[i], j, T.ch[j]); 183 if(S.ch[i] == T.ch[j] || j == 0){ 184 i += 1; 185 j += 1; 186 }else{ 187 j = next[j]; 188 LOG("用优化后的KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到%d", j); 189 } 190 } 191 free(next); 192 if(j>=T.length){ 193 //匹配成都 194 return i-T.length; 195 }else{ 196 return 0; 197 } 198 } 199 200 201 202 int main(int argc, char *argv[]) 203 { 204 int ret = -1; 205 int pos = 0; 206 HString S1, S2, T, Sub, S; 207 S1.ch = S2.ch = T.ch = Sub.ch = S.ch = NULL; 208 S1.length = S2.length = T.length = Sub.length = 0; 209 210 ret = StrAssign(&S1, "hbcde"); 211 LOG("设置变量S1为%s", S1.ch); 212 213 ret = StrAssign(&S2, "ghijklm"); 214 LOG("设置变量S2为%s", S2.ch); 215 216 ret = StrCompare(S1, S2); 217 LOG("较字符串S1和S2的大小, 返回值为%d", ret); 218 219 ret = Concat(&T, S1, S2); 220 LOG("将字符串S1和S2拼接,并将值保存到T; 结果使得变量T为%s", T.ch); 221 222 ret = SubString(&Sub, T, 4, 3); 223 LOG("求字符串T中起始4开始、长度为3的子串,并将子串放到变量Sub; 结果使得变量Sub为%s, (下标从1开始)", Sub); 224 225 LOG("清空S1、S2、T、Sub变量的内容"); 226 ClearString(&S1); 227 ClearString(&S2); 228 ClearString(&T); 229 ClearString(&Sub); 230 231 ret = StrAssign(&S, "acabaabaabcacaabc"); 232 LOG("设置变量S为%s", S.ch); 233 234 ret = StrAssign(&T, "abaabc"); 235 LOG("设置变量T为%s", T.ch); 236 237 LOG("求字串S中位置pos开始,是否存在子串T; 如果存在,则返回字串T在S中的位置下标"); 238 LOG("方法一:普通方法"); 239 ret = Index(S, T, pos); 240 LOG("普通方法: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)\n", S.ch, pos, T.ch, ret); 241 242 LOG("方法二:用KMP方法,例1"); 243 ret = Index_KMP(S, T, pos); 244 LOG("用KMP方法,例1: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)\n", S.ch, pos, T.ch, ret); 245 246 ret = StrAssign(&S, "aaabaaaab"); 247 LOG("设置变量S为%s", S.ch); 248 249 ret = StrAssign(&T, "aaaab"); 250 LOG("设置变量T为%s", T.ch); 251 252 LOG("方法二:用KMP方法,例2"); 253 ret = Index_KMP(S, T, pos); 254 LOG("用KMP方法,例2: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)\n", S.ch, pos, T.ch, ret); 255 256 257 LOG("方法三:用改进后的KMP方法"); 258 ret = Index_KMP_Val(S, T, pos); 259 LOG("用改进后的KMP方法: 求字串S(%s)中位置pos(%d)开始,是否存在子串T(%s); 返回的下标为%d (下标从0开始)", S.ch, pos, T.ch, ret); 260 return 0; 261 } 262 263 264 265 ////////////////////////////////////////////////////////////////////////// 266 static int StrAssign(HString *T, const char *chars) 267 { 268 if(T == NULL){ 269 return -1; 270 } 271 if(T->ch){ 272 free(T->ch); 273 T->ch = NULL; 274 } 275 int len = strlen(chars); 276 if((T->ch = malloc(len+1)) == NULL){ 277 return -1; 278 } 279 memset(T->ch, 0, len+1); 280 T->length = len; 281 snprintf(T->ch, len+1, "%s", chars); 282 return 0; 283 } 284 285 static int StrLength(HString S) 286 { 287 return S.length; 288 } 289 290 static int StrCompare(HString S, HString T) 291 { 292 int i = 0; 293 for(i=0; i<S.length && i<T.length; ++i){ 294 if(S.ch[i] != T.ch[i]){ 295 return S.ch[i] - T.ch[i]; 296 } 297 } 298 return S.length - T.length; 299 } 300 301 static int ClearString(HString *S) 302 { 303 if(S->ch){ 304 free(S->ch); 305 S->ch = NULL; 306 } 307 S->length = 0; 308 return 0; 309 } 310 static int Concat(HString *T, HString S1, HString S2) 311 { 312 if(T->ch){ 313 free(T->ch); 314 T->ch = NULL; 315 } 316 if((T->ch = (char*)malloc((S1.length+S2.length)*sizeof(char))) == NULL){ 317 return -1; 318 } 319 strncpy(T->ch, S1.ch, S1.length); 320 strncpy(T->ch+S1.length, S2.ch, S2.length); 321 T->length = S1.length + S2.length; 322 T->ch[T->length] = ‘\0‘; 323 return 0; 324 } 325 326 static int SubString(HString *Sub, HString S, int pos, int len) 327 { 328 if(pos<1 || pos>S.length || len<0 || len>S.length-pos+1){ 329 return -1; 330 } 331 if(Sub->ch){ 332 free(Sub->ch); 333 Sub->ch = NULL; 334 } 335 if(!len){ 336 Sub->ch = NULL; 337 Sub->length = 0; 338 }else{ 339 Sub->ch = (char *)malloc(len*sizeof(char)+1); 340 memset(Sub->ch, 0, len); 341 strncpy(Sub->ch, S.ch+pos-1, len); 342 Sub->length = len; 343 Sub->ch[len] = ‘\0‘; 344 } 345 return 0; 346 }
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled 设置变量S1为hbcde 设置变量S2为ghijklm 较字符串S1和S2的大小, 返回值为1 将字符串S1和S2拼接,并将值保存到T; 结果使得变量T为hbcdeghijklm 求字符串T中起始4开始、长度为3的子串,并将子串放到变量Sub; 结果使得变量Sub为deg, (下标从1开始) 清空S1、S2、T、Sub变量的内容 设置变量S为acabaabaabcacaabc 设置变量T为abaabc 求字串S中位置pos开始,是否存在子串T; 如果存在,则返回字串T在S中的位置下标 方法一:普通方法 普通方法: 比较S.ch[0]=a 和 T.ch[0]=a 普通方法: 比较S.ch[1]=c 和 T.ch[1]=b 普通方法: 两者不等,需把S的下标i回退到1, 把T的下标j回退到0 普通方法: 比较S.ch[1]=c 和 T.ch[0]=a 普通方法: 两者不等,需把S的下标i回退到2, 把T的下标j回退到0 普通方法: 比较S.ch[2]=a 和 T.ch[0]=a 普通方法: 比较S.ch[3]=b 和 T.ch[1]=b 普通方法: 比较S.ch[4]=a 和 T.ch[2]=a 普通方法: 比较S.ch[5]=a 和 T.ch[3]=a 普通方法: 比较S.ch[6]=b 和 T.ch[4]=b 普通方法: 比较S.ch[7]=a 和 T.ch[5]=c 普通方法: 两者不等,需把S的下标i回退到3, 把T的下标j回退到0 普通方法: 比较S.ch[3]=b 和 T.ch[0]=a 普通方法: 两者不等,需把S的下标i回退到4, 把T的下标j回退到0 普通方法: 比较S.ch[4]=a 和 T.ch[0]=a 普通方法: 比较S.ch[5]=a 和 T.ch[1]=b 普通方法: 两者不等,需把S的下标i回退到5, 把T的下标j回退到0 普通方法: 比较S.ch[5]=a 和 T.ch[0]=a 普通方法: 比较S.ch[6]=b 和 T.ch[1]=b 普通方法: 比较S.ch[7]=a 和 T.ch[2]=a 普通方法: 比较S.ch[8]=a 和 T.ch[3]=a 普通方法: 比较S.ch[9]=b 和 T.ch[4]=b 普通方法: 比较S.ch[10]=c 和 T.ch[5]=c 普通方法: 求字串S(acabaabaabcacaabc)中位置pos(0)开始,是否存在子串T(abaabc); 返回的下标为5 (下标从0开始) 方法二:用KMP方法,例1 KMP算法中字串(abaabc)的next函数值: next[0]=0 KMP算法中字串(abaabc)的next函数值: next[1]=0 KMP算法中字串(abaabc)的next函数值: next[2]=0 KMP算法中字串(abaabc)的next函数值: next[3]=1 KMP算法中字串(abaabc)的next函数值: next[4]=1 KMP算法中字串(abaabc)的next函数值: next[5]=2 用KMP方法: 比较S.ch[0]=a 和 T.ch[0]=a 用KMP方法: 比较S.ch[1]=c 和 T.ch[1]=b 用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0 用KMP方法: 比较S.ch[1]=c 和 T.ch[0]=a 用KMP方法: 比较S.ch[2]=a 和 T.ch[1]=b 用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0 用KMP方法: 比较S.ch[2]=a 和 T.ch[0]=a 用KMP方法: 比较S.ch[3]=b 和 T.ch[1]=b 用KMP方法: 比较S.ch[4]=a 和 T.ch[2]=a 用KMP方法: 比较S.ch[5]=a 和 T.ch[3]=a 用KMP方法: 比较S.ch[6]=b 和 T.ch[4]=b 用KMP方法: 比较S.ch[7]=a 和 T.ch[5]=c 用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到2 用KMP方法: 比较S.ch[7]=a 和 T.ch[2]=a 用KMP方法: 比较S.ch[8]=a 和 T.ch[3]=a 用KMP方法: 比较S.ch[9]=b 和 T.ch[4]=b 用KMP方法: 比较S.ch[10]=c 和 T.ch[5]=c 用KMP方法,例1: 求字串S(acabaabaabcacaabc)中位置pos(0)开始,是否存在子串T(abaabc); 返回的下标为5 (下标从0开始) 设置变量S为aaabaaaab 设置变量T为aaaab 方法二:用KMP方法,例2 KMP算法中字串(aaaab)的next函数值: next[0]=0 KMP算法中字串(aaaab)的next函数值: next[1]=0 KMP算法中字串(aaaab)的next函数值: next[2]=1 KMP算法中字串(aaaab)的next函数值: next[3]=2 KMP算法中字串(aaaab)的next函数值: next[4]=3 用KMP方法: 比较S.ch[0]=a 和 T.ch[0]=a 用KMP方法: 比较S.ch[1]=a 和 T.ch[1]=a 用KMP方法: 比较S.ch[2]=a 和 T.ch[2]=a 用KMP方法: 比较S.ch[3]=b 和 T.ch[3]=a 用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到2 用KMP方法: 比较S.ch[3]=b 和 T.ch[2]=a 用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到1 用KMP方法: 比较S.ch[3]=b 和 T.ch[1]=a 用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0 用KMP方法: 比较S.ch[3]=b 和 T.ch[0]=a 用KMP方法: 比较S.ch[4]=a 和 T.ch[1]=a 用KMP方法: 比较S.ch[5]=a 和 T.ch[2]=a 用KMP方法: 比较S.ch[6]=a 和 T.ch[3]=a 用KMP方法: 比较S.ch[7]=a 和 T.ch[4]=b 用KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到3 用KMP方法: 比较S.ch[7]=a 和 T.ch[3]=a 用KMP方法: 比较S.ch[8]=b 和 T.ch[4]=b 用KMP方法,例2: 求字串S(aaabaaaab)中位置pos(0)开始,是否存在子串T(aaaab); 返回的下标为4 (下标从0开始) 方法三:用改进后的KMP方法 优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[0]=0 优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[1]=0 优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[2]=0 优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[3]=0 优化后的KMP算法中字串(aaaab)的nextval函数值: nextval[4]=3 用优化后的KMP方法: 比较S.ch[0]=a 和 T.ch[0]=a 用优化后的KMP方法: 比较S.ch[1]=a 和 T.ch[1]=a 用优化后的KMP方法: 比较S.ch[2]=a 和 T.ch[2]=a 用优化后的KMP方法: 比较S.ch[3]=b 和 T.ch[3]=a 用优化后的KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到0 用优化后的KMP方法: 比较S.ch[3]=b 和 T.ch[0]=a 用优化后的KMP方法: 比较S.ch[4]=a 和 T.ch[1]=a 用优化后的KMP方法: 比较S.ch[5]=a 和 T.ch[2]=a 用优化后的KMP方法: 比较S.ch[6]=a 和 T.ch[3]=a 用优化后的KMP方法: 比较S.ch[7]=a 和 T.ch[4]=b 用优化后的KMP方法: 两者不等,需把S的下标i保持不变, 把T的下标j回退到3 用优化后的KMP方法: 比较S.ch[7]=a 和 T.ch[3]=a 用优化后的KMP方法: 比较S.ch[8]=b 和 T.ch[4]=b 用改进后的KMP方法: 求字串S(aaabaaaab)中位置pos(0)开始,是否存在子串T(aaaab); 返回的下标为4 (下标从0开始) Process finished with exit code 0
原文:https://www.cnblogs.com/aimmiao/p/10800380.html