串->串的表示和实现

文字描述:

串,就是字符串的意思。在数据结构中,串的存储方式有三种:定长顺序存储表示、堆分配存储表示和块链存储表示:

定长顺序存储表示:  以一组地址连续的存储单元存放字符序列,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。超出预定义的串值会被舍弃,成为“截断”。

堆分配存储表示: 以一组地址连续的存储单元存放字符序列,但它们的存储空间是在执行时动态分配而得。

块链存储表示: 和线性表的链式存储结构类似,如下图,一个是结点大小为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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下载好代码后直接在linux环境下减压,make之后即可产生可执行代码,压缩文件中已经包含了可执行代码。 通过的堆分配存储结构来实现的以下功能: //生成一个值等于常量chars的string int StrAssign(HString *str,char *chars); //返回string的长度 int StrLength(HString str); //比较两个的大小,如果str1 > str2,返回值>0,如果相等,返回0,如果str1 < str2,返回值<0 int StrCompare(HString str1,HString str2); //清空,释放所占用的空间 int ClearString(HString *str); //返回Str1和Str2联合而成的 HString Concat(HString str1,HString str2); //返回str的第pos个字符之后的长度为len的子 HString SubString(HString str,int pos,int len); //显示字符 int StrTrave(HString str); //-----------------------附加操作函数-------------------------- //以下操作可由基本操作来实现 //str1复制得到str2 int StrCopy(HString str1,HString *str2); //str为空,返回1,否则返回0 int StrEmpty(HString str); //如果主str中存在和substr相等的子,则返回子在主中pos个字符之后第一次出现的位置 ,运用了KMP算法 int Index(HString str,HString substr,int pos); //Index中包括了一个静态函数get_next(),这个函数可以得到字符的最简匹配值(kmp算法中字符匹配失败后的下一个最佳匹配值) //用字符Tstr替换主str中出现的所有与substr相等的子 int StrReplace(HString **str,HString substr,HString Tstr); //在str的第pos个字符之后插入substr int StrInsert(HString *str,HString substr,int pos); //从str的第pos个字符起删除len个字符 int StrDelete(HString **str,int pos,int len); //销毁现有str int StrDestory(HString *str);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值