1 / 29

第四章 串

第四章 串. 本章内容. 串的数据类型定义; 串的几种存储结构: 顺序存储结构; 单链表存储结构; 堆分配存储结构; 串的各种基本操作的实现及其应用; 串的模式匹配算法。. 本章要点. 熟悉串的 5 种基本操作的定义,并能利用这些基本操作实现串的其它各种操作的方法; 熟练掌握在串的顺序存储结构基础上实现的串的各种操作的方法; 掌握串的分块存储结构以及在其上实现串操作的基本方法; 理解串匹配的 KMP 算法; 了解串操作的应用方法和特点。. 4.1 串类型的定义. 串 是零个或多个字符组成的有限序列;

adele
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. 第四章 串

  2. 本章内容 • 串的数据类型定义; • 串的几种存储结构: • 顺序存储结构; • 单链表存储结构; • 堆分配存储结构; • 串的各种基本操作的实现及其应用; • 串的模式匹配算法。

  3. 本章要点 • 熟悉串的5种基本操作的定义,并能利用这些基本操作实现串的其它各种操作的方法; • 熟练掌握在串的顺序存储结构基础上实现的串的各种操作的方法; • 掌握串的分块存储结构以及在其上实现串操作的基本方法; • 理解串匹配的KMP算法; • 了解串操作的应用方法和特点。

  4. 4.1 串类型的定义 • 串 • 是零个或多个字符组成的有限序列; • 一般记作S="a0a1a2…an-1" • S 是串名,单引号括起来的字符序列是串值 • ai(0≦i<n)可以是字母、数字或其它字符 • 串的长度:串中所包含的字符个数 • 空串(Empty String):长度为零的串,它不包含任何字符。 • 空白串(Blank String):仅由一个或多个空格组成的串; • 空串和空白串不同: • " "和""分别表示长度为1的空白串和长度为0的空串。

  5. 串类型的定义(续) • 子串 • 串中任意个连续字符组成的子序列称为该串的子串; • 主串 • 包含子串的串称为主串。 • 子串在主串中的位置 • 子串在主串中首次出现时,该子串的首字符对应的主串中的位置 • 模式匹配 • 在主串中找到等于给定串的子串的过程,即子串的定位操作; • 结果 • 匹配成功,返回子串第一个字符在主串中的位置 • 匹配失败 • 空串是任意串的子串,任意串是其自身的子串。 • 串的相等:两串的长度及对应位置的字符均相等。

  6. 串的基本运算 • 用串变量赋值 assign(s,t) • 用串常量赋值 creat(s,ss) • 判等函数 equal(s,t) • 求长函数 length(s) • 连接函数 concat(s,t) • 求子串函数 substr(s,start,len) • 定位函数 index(s,t) • 置换函数 replace(s,t,v)用v替换s中的t • 插入操作 insert(s,pos,t) • 删除操作 delete(s,pos,len) • 线性表的操作通常以“数据元素”为操作对象; • 串的操作主要以“串的整体”为操作对象。

  7. 4.2 串的表示和实现 定长顺序存储表示 堆分配存储表示 串的块链存储表示

  8. 串的顺序存储结构 #define MaxLen 256 1. typedef char string[MaxLen]; string s; 2. typedef struct string { char str[MaxLen]; int length; };

  9. 高级语言中的字符串表示 • C语言字符串的存储格式 (ASCIIZ) • 字符串尾部存放0 • 举例 • Pascal语言字符串的存储格式(nASCII) • s[0]存放字符串长度 • 举例 • 优缺点对比

  10. Head A S T R I N G ∧ ∧ Head A R I S N T G 串的链式存储结构 (块链结构) #define MaxLen 256 typedef struct node { char data[MaxLen]; struct node *next; };

  11. 串的堆分配存储结构 • 串的存储空间在程序执行过程中动态分配而得 • malloc() • free() • 优点 • 具有顺序存储结构的优点,处理方便 • 对串长没有任何限制,灵活 typedef char *string; typedef struct string { char *data; int length; };

  12. 4.3 串的模式匹配算法 • 模式匹配 • 模式串:子串 • 在主串中找到模式串的过程,即子串的定位操作 • 结果 • 匹配成功,返回子串第一个字符在主串中的序号 • 匹配失败,返回0 • 算法思想 • 主串s,子串p:Index(s, p) • 将s中的第一个字符与p中的第一个字符进行比较; • 若不同,就将s中的第二个字符与p中的第一个字符进行比较...,直到s的某一个字符和p的第一个字符相同,将它们之后的字符进行比较 • 若相同,将它们之后的字符进行比较 • 当s的某一个字符si与p的字符pj不同时,则s,p回退,即:将s中的第i-j+2个和p的第一个字进行比较,重复上述过程

  13. int Index(string S, string p) { i = j = 1; while (i <= S[0] && j <= p[0]){ if (S[i] == p[j]) { i++; j++; } else { i = i - j + 2; j = 1; } } return j > p[0] ? i - p[0] : 0; } 模式匹配结果 成功,返回子串在主串中第一次出现的位置 失败,返回 0 时间复杂度 最坏:为 O(m·n),其中m和 n 分别为 s 串和 t 串的长度 最好:O(n) 算法特点 匹配过程易于理解 匹配过程中,对主串的访问需要回退 朴素的模式匹配算法

  14. a b c d a b e g k=3 本趟比较失配点:i=7, j=7 (即s7p7) 失配点处p1p2=s5s6=p5p6p1…pk-1=pj-k+1…pj-1 下趟比较:i不变,j=k(此处即3) 模式匹配算法的改进 [改进之处] 在比较过程中,主串的下标i只增不减,不回退,可使算法复杂度提高到O(m+n) [分析] 1 2 3 4 5 6 7 8 9 10 11 12 13 主串s a b c d a b c d a b e g h s1s2…sn 子串t a b c d a b e g p1p2…pm i=7 m<n j=7

  15. { 不考虑 j=1 Next[j] = Max { k | 1<k<j 且 p1p2…pk-1=pj-k+1pj-k+2 …pj-1 } 1 其它情况 算法改进 int Index(string S, string p) { i = j = 1; while ( i <= S[0] && j <= p[0] ) { if (S[i] == p[j] ) { i++; j++; } else if (j == 1) { i++; j =1; } else j = next[j]; } return j>p[0] ? i - p[0] : 0; }

  16. { 0 j=1 Next[j] = Max { k | 1<k<j 且 p1p2…pk-1=pj-k+1pj-k+2 …pj-1 } 1 其它情况 算法进一步改进(KMP算法) int Index(string S,string p) { i = j = 1; while ( i <= S[0] && j <= p[0] ) { if (j==0 || S[i] == p[j] ) { i++; j++; } else j = next[j]; } return j>p[0] ? i - p[0] : 0; }

  17. { 0 当 j=1 时 Next[j] = Max { k | 1<k<j 且 p1p2…pk-1=pj-k+1pj-k+2 …pj-1 } 1 其它情况 KMP算法 由 D.E.Knuth 与 J.H.Morris 和 V.R.Pratt 同时提出; 没有回溯的模式匹配算法; 用 s[i] 与 p[j] 匹配,若相等则往后继续匹配,否则就用s[i]与p[next[j]]匹配,直至匹配成功或失败为止

  18. s k 1 1 k j -k+1 KMP 算法原理 当 s[i] 与 p[j] 不匹配时,s[i] 就与 p[next[j]] 比较 i j p Next[j] = k

  19. 模式串的next求值 • next值仅取决于模式串本身,与主串无关 • 设next[i]=k,则next[i+1]=? • 由next[i]=k有:p1…pk-1=pi-k+1…pi-1 • 若pk==pi • p1…pk-1pk=pi-k+1…pi-1pi,next[i+1] =k+1=next[i]+1 • 若pk≠pi • p1…pk-1pk ≠pi-k+1…pi-1pi • 当pk≠pi时,应将模式向右滑动至模式的第next[k]=k’个字符和主串的失败字符继续比较 • 若pk’==pi,则有p1…pk’=pi-k’+1…pi (1<k’<k<i) • next[i+1]=k’+1=next[k]+1 • 若pk’ ≠pi,将模式向右滑动至模式的第next[k’]个字符和主串的第i个字符相比较,依次类推,直至next[i+1]=1

  20. 求next函数值的算法演化(1) 循环: /* k记录next[i] */ if (p[i]==p[k]) { next[i+1] = k + 1; i++; k++; /* 为下次循环做好准备*/ } else { /* i不变,以便继续求解next[i+1] */ k = next[k]; }

  21. 求next函数值的算法演化(2) 循环: if (k == 0) { next[i+1] = 1; i++; k = 1; } else if (p[i]==p[k]) { next[i+1] = k + 1; i++; k++; /* 为下次循环做好准备*/ } else { /* i不变,以继续求解next[i+1] */ k = next[k]; }

  22. 求next函数值的算法演化(3) i = 1; (需要对K赋初值) while (i < p[0]) { if (k == 0 || p[i] == p[k]) { i++; k++; next[i] = k; } else k = next[k]; }

  23. j 1 2 3 4 5 6 7 8 9 10 11 a a b c a a a b c a d 模式串 求next函数值 i = 1; next[1] = 0; k = 0; while (i < p[0]) { if (k == 0 || p[i] == p[k]) { i++; k++; next[i] = k; } else k = next[k]; } next 0 1 2 1 1 2 3 3 4 5 6

  24. Next数组的缺陷 例j 1 2 3 4 5 6 7 8 9 10 11 a b c a b c a b b a c next[j] 0 1 1 1 2 3 4 5 6 1 2 s= a b c a b c a x a b c a b c a b b a c t= a b c a b c a b b a c next[8]=5 a b c a b c a b b a c next[5]=2 a b c a b c a b b a c next[2]=1 a b c a b c a b b a c 存在p8=p5=p2, 因此当s8p8时,s8与p5,p2的比较无意义

  25. KMP 算法的改进 已知next[i],如何求解next[i+1]? 设next[i]=k, 当p[i]=p[k]并且p[i+1]与p[k+1]相同时,就将next[k+1]赋给next[i+1],即为 nextval 数组。

  26. 改进的 KMP 算法实现 i=1; k=0; nextval[1]=0; while (i<T[0]) { if (k==0 || p[i] == p[k]) { i++; k++; if (p[i] != p[k]) nextval[i] = k; else nextval[i] = nextval[k]; } else k=nextval[k]; }

  27. j 1 2 3 4 5 6 7 8 9 10 11 a a b c a a a b c a d 模式串 求nextval的例子 nextval 0 0 2 1 0 0 3 2 1 0 6 例j 1 2 3 4 5 6 7 8 9 10 11 a b c a b c a b b a c nextval[j] 0 1 1 0 1 1 0 1 6 0 2

  28. KMP算法时间复杂度分析 • 通常,模式串长度m<<主串长度n • 求next(nextval)数组:O(m) • 主串与模式串匹配: O(n) • 整个匹配算法O(m+n)

  29. 作业 1.参阅81页KMP算法中,next数组的定义。 (1)为什么j=1时,next[j]=0? (2)为什么要取max(k),k的最大值是什么? (3)其他情况是什么情况?为什么取next[j]=1? 2.(1)求出下列模式串的next数组值 t1="abcaabbcabcaabdab" t2="ababaaababaa" (2)求出下列模式串的nextval数组值 t1="abcaabbcabcaabdab" t2="ababaabab" 3.写出对串求逆的递归算法。

More Related