1 / 25

第四章 串

第四章 串. 4.1 串及其运算 是由零个或多个字符组成的有限序列,一般记为 s=“a 1 a 2 …a n ”(n  0) 其中, s 是串名,用单引号(也可以是用双引号括起来的) 括起来的字符序列是串的值。 a i 可以是字母、数字或其他字符;串中字符的个数 n 成为串的长度。. 子串: 串中任意个 连续 的字符组成的子序列。 主串: 包含子串的串相应地称为主串。 位置: 字符在序列中的序号。子串在主串中的位置则以子 串的 第一个 字符在主串中的位置来表示。 相等: 两个串的长度相等,并且对应位置的字符都相等。.

shayna
Download Presentation

第四章 串

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第四章 串 4.1 串及其运算 是由零个或多个字符组成的有限序列,一般记为 s=“a1a2…an”(n0) 其中,s是串名,用单引号(也可以是用双引号括起来的) 括起来的字符序列是串的值。ai可以是字母、数字或其他字符;串中字符的个数n成为串的长度。

  2. 子串:串中任意个连续的字符组成的子序列。 主串:包含子串的串相应地称为主串。 位置:字符在序列中的序号。子串在主串中的位置则以子 串的第一个字符在主串中的位置来表示。 相等:两个串的长度相等,并且对应位置的字符都相等。 注意区分空串与空格串的区别。

  3. 串的逻辑结构和线性表的区别: 1. 串的数据对象约束为字符集。 2. 线性表的基本操作大多以“单个元素”为操作对象,而 串的基本操作通常以“串的整体”作为操作对象。 对于串可以定义以下运算: 1. 置串为一个空串; 2. 判断一个串是否为空串 3. 求一个串的长度; 4. 将两个串拼接在一起构成一个新串; 5. 在一个串中,求从串的第i个字符开始连续j个字符所构成的子串; 6. 如果串S2是S1的子串,则可求串S2在串S1中第一次出现的位置。

  4. 4.2串的存储表示 1. 定长顺序表示 #define MAXNUM 1000 /* 串允许的最大字符个数 */ struct SeqString /* 顺序串的类型 */ { char c[MAXNUM]; int n; }SeqString, *PSeqString;

  5. 算法4.1 求顺序表示的串的子串 PSeqString subStr_seq(PSeqString s,int i,int j) /* 求从s所指的顺序串中第i(i>0)个字符开始连续j个字符所构成的子串 */ { PSeqString s1; int k,m; s1 = createNullStr_seq( ); if (s1==NULL) return NULL; if ( i>0 && i<=s->n && j>0 ) { if ( s->n < i+j-1 ) j = s->n -i+1; for (k=0;k<j;k++) s1->c[k]=s->c[i+k-1]; s1->c[j]='\0'; s1->n =j; } else s1->c[0]='\0'; return(s1); }

  6. 算法4.2 创建空顺序串 PSeqString createNullStr_seq( void ) { PSeqString pstr; pstr=(PSeqString)malloc(sizeof(struct SeqString)); if (pstr==NULL) printf("Out of space!!\n"); else pstr->n = 0; return pstr; }

  7. 2. 变长顺序表示 typedef struct { char *ch; int length; }HString; void StrAssign(HString *str, char *chars); void StrCopy(HString *dest, HString src); void StrCopyN(HString *dest, HString src, int n); BOOL IsStrEmpty(HString str); int StrCompare(HString str1, HString str2); int StrLength(HString str); void ClearString(HString *str); Status StrCat(HString *dest, HString str1, HString str2); ……

  8. void StrAssign(HString *str, char *chars) { char *p = chars; int length, i; if(str->ch) /* 释放已有空间 */ { free(str->ch); str->ch = NULL; str->length = 0; } while(*p!=‘#’) p++ ; /* 求串长 */ length = p - chars - 1; if(length == 0) str->length = 0; else{ /* 重新申请空间 */ str->length = length; str->ch = (char *)malloc(sizeof(char)*length); assert(str->ch); for(i=0; i<length; i++) str->ch[i] = chars[i]; } } /* End of StrAssign() */

  9. void StrCopy(HString *dest, HString src) { char *p; int i; if(dest->ch) { free(dest->ch); dest->ch = NULL; } p = (char *)malloc(sizeof(char) * src.length); assert(p); dest->ch = p; dest->length = src.length; for(i=0; i<src.length; i++) p[i] = src.ch[i]; } for(i=0; i<src.length; i++) p[i] = src.ch[i]; dest->ch = p; dest->length = src.length;

  10. 提取子串的算法示例 pos = 2, len = 3 pos = 5, len = 4 i n f i n i t y i n f i n i t y 超出 f i n i t y pos+len -1 pos+len -1  curLen-1  curLen

  11. Status SubString(HString *sub, HString str, int pos, int len) {/* 0 <= pos < str.length and 0 <= len <= str.length-pos+1 用sub返回串str的第pos个字符起长度为len的子串*/ int i; if(pos < 0 || pos >= str.length || len < 0 || len > str.length-pos+1) return ERROR; if(sub->ch){ free(sub->ch); sub->ch = NULL; } if(!len){ sub->ch = NULL; sub->length = 0; } else{ sub->ch = (char *)malloc(sizeof(char) * len); assert(sub->ch); for(i=0; i<len; i++) str->ch[i] = str[pos+i]; sub->length = len; } return OK; } /* End of SubString() */

  12. 4. 串的块链存储表示 #define ChunkSize 80 typedef struct _StrNode { char c; struct _StrNode *link; }StrNode; typedef struct { StrNode *head; }LinkString, *PLinkString, *PStrNode;

  13. (a) 单链表表示 (b) 循环表表示

  14. 四、模式匹配与KMP算法 • 模式匹配 • 在一个源串中搜索模式串的出现位置 源串:"This is a demo string!" 模式串:"is a"

  15. 四、模式匹配与KMP算法 • 朴素模式匹配算法 源串: This is a demo string! 模式串:is a is a is a is a is a is a is a

  16. 四、模式匹配与KMP算法 • KMP算法 • 问题的提出——一个极端的例子 源串: aaaaaaaaaab 模式串:aaaab aaaab aaaab aaaab aaaab aaaab aaaab aaaab

  17. nextval[4]=3 四、模式匹配与KMP算法 • KMP算法 • 算法思想——nextval向量 下标:01234 源串: aaaa???????? 模式串:aaaab aaaab aaaab

  18. nextval[4]=-1 四、模式匹配与KMP算法 • KMP算法 • 算法思想——nextval向量 下标:01234 源串: aaaa???????? 模式串:aaaaa aaaaa aaaaa

  19. 四、模式匹配与KMP算法 • KMP算法 • nextval向量的定义 • 对模式串T[0…n-1],定义向量nextval[0…n-1]如下:nextval[i]表示:当T[i]匹配失败时,下一次必要的匹配比较是用T[nextval[i]]与源串的当前字符进行比较;若模式串已不可能与源串的当前位置形成匹配,则记nextval[i]为一个特殊值,如-1。

  20. 四、模式匹配与KMP算法 • KMP算法 • nextval向量举例 -1 0 -1 0 -1 0 4 0 -1

  21. 四、模式匹配与KMP算法 • KMP算法 • 在nextval向量指导下进行模式匹配 • 在源串和模式串上分别设立扫描指针i和j,从串首开始; • 对源串和模式串的当前字符进行比较,直到源串或模式串扫描完毕: • 若相等,则两个扫描指针同步前进; • 否则,模式串扫描指针前移到nextval向量指示的位置,若nextval[i]为预定特殊值,则源串扫描指针前进,模式串扫描指针回到串首; • 若模式串扫描完毕,则匹配成功,否则匹配失败。 CODING

  22. 四、模式匹配与KMP算法 • KMP算法 • nextval向量的计算 • nextval向量的性质 • 最大相同首真子串与尾真子串 最大相同首真子串与尾真子串

  23. sj-i~sj-1=t0~ti-1(ti之前已经匹配成功) • sj≠ti(ti匹配失败) • t0~tk-1=ti-k~ti-1(根据模式串可以确定的可匹配部分) • 不存在更大的满足条件3和5的k值(以保证匹配的必要性) • ti≠tk(若ti=tk,则不须比较即可推知:sj≠tk) 前提条件 k为最大相同首真子串和尾真子串的长度 k即nextval[i]

  24. 四、模式匹配与KMP算法 • KMP算法 • 最大相同首真子串与尾真子串的长度的计算 • 将T[0…i-1]的最大相同首真子串与尾真子串的长度,记为Ki • 设已知Ki-1,求Ki: • 令k从Ki-1开始; • 若k=-1(特殊值),则Ki=0; • 若t[k]=t[i-1],则Ki=k+1; • 否则,将k前推至nextval[k],重复2;

  25. 四、模式匹配与KMP算法 • KMP算法 • nextval向量的计算 • 计算nextval[i]: • 先计算T[0…i-1]的最大相同首真子串与尾真子串的长度Ki; • 如果T[i]≠T[Ki],则nextval[i]=Ki,否则nextval[i]=nextval[Ki] CODING

More Related