42
子子子子子子子子子子子子子子子子子 子子子子子子子子子子子 子子子 子子子子子子 ,。, 子子子子子子子 子子子子子子子子子子 子子子子子子子子子子子子子子子子子子子 ,一。 子子子子子子子子子子子子子子子 : 子子子子子子子子子子子子子子 子子子子子子子 子子子子 。, 子子子 子子子子子子子子子子 子子子子子子 子子子子子 子子 一,, 子子子子 子子子子子子 子子子子子 子子 一,, “子子” “子子” 子子子子子 子子子子子 子子子子子 子子子子子 “子子” “子子” 子子子子子子子子 4. 3 子子子子子子子子 ( 子子子子 )

这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

  • Upload
    kimama

  • View
    109

  • Download
    6

Embed Size (px)

DESCRIPTION

4. 3 串的模式匹配算法 ( 知识点三 ). 子串定位运算又称为模式匹配或串匹配,此运算的应用非常广泛。例如,文本编辑程序中,经常要查找某一特定单词出现的位置。解此问题的有效算法能极大地提高文本编辑程序的响应性能。 串的模式匹配定义 : 在主串中寻找子串在串中的位置。在模式匹配中,子串称为 模式串 ,主 串称为 目标串 。. 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。. 4. 3.1 求子串位置的定位函数 Index(S,T,pos). - PowerPoint PPT Presentation

Citation preview

Page 1: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

子串定位运算又称为模式匹配或串匹配,此运算的应用非常广泛。例如,文本编辑程序中,经常要查找某一特定单词出现的位置。解此问题的有效算法能极大地提高文本编辑程序的响应性能。串的模式匹配定义 : 在主串中寻找子串在串中的位置。在模式匹配中,子串称为模式串,主串称为目标串。 这是串的一种重要操作,很多软件,若有这是串的一种重要操作,很多软件,若有“编辑”“编辑”菜菜单项的话,则其中必有单项的话,则其中必有“查找”“查找”子菜单项。子菜单项。

4. 3 串的模式匹配算法 ( 知识点三 )

Page 2: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

Index(S,T,pos)Index(S,T,pos) 称为称为模式匹配模式匹配(( SS 为主串, 为主串, TT 为模式串为模式串 ););初始条件初始条件 :S:S 和和 TT 存在存在 ,T,T 是非空串是非空串 ,,

1 <= pos <= 1 <= pos <= (( SS 的长度)。的长度)。操作结果操作结果 :: 若主串若主串 SS 中存在和串中存在和串 TT 相同的(相同的(模式串模式串 )子串,则返回)子串,则返回它在主串它在主串 SS 中第中第 pospos 个字符之后第一次出现的位置;否则返回0。个字符之后第一次出现的位置;否则返回0。

4. 3.1 求子串位置的定位函数 Index(S,T,pos)Index(S,T,pos)

例如:对某文本进行编辑时,可以运用如下步骤:( 1 )编辑;( 2 )查找 ——“输入查找文本(字符串)”;( 3 )找出对应 的串

Page 3: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

Abcdefghijklmnopqrstuvw

T 串

pos=4

defghijk

S 串

按照上述主串 S 和子串 T 求子串位置的定位函数 Index(S,T,pos)Index(S,T,pos) 的返回值是的返回值是 44

Page 4: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

int Index (SString S, SString T, int pos) { // 返回子串 T 在主串 S 中第 pos 个字符之后的位置。若不存在, // 则函数值为 0 。其中, T 非空, 1≤pos≤StrLength(S) 。 i = pos; j = 1; while (i <= S[0] && j <= T[0]) { if (S[i] == T[j]) { ++i; ++j; } // 继续比较后继字符 else { i = i-j+2; j = 1; } // 指针后退重新开始匹配 } if (j > T[0]) return i-T[0]; else return 0;} // Index

p79 算法 4.5

Page 5: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

主串 s= " ababcabcacbab ",模式 T= " abcac "

b

i=11

J=6

主串 s 模式串 T = " abcac "

模式串 T = " abcac "

模式串 T = " abcac "

i=6

if (S[i] == T[j]) { ++i; ++j; } // 继续比较后继字符 else { i = i-j+2; j = 1; }

核心语句

返回值为 11-5=6

因为 T[0]=5

Page 6: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

算法 4.5 Index(S,T,pos) Index(S,T,pos) 即模式匹配的特点:即模式匹配的特点: 特点一: Index(S,T,pos) Index(S,T,pos) 算法的匹配方法简单,理解方便,适合一些文本编辑,效算法的匹配方法简单,理解方便,适合一些文本编辑,效率较高;率较高; 特点二: Index(S,T,pos) Index(S,T,pos) 算法的匹配方法简单,理解方便,适合一些文本编辑,效算法的匹配方法简单,理解方便,适合一些文本编辑,效率较高;正常情况下,时间复杂度为率较高;正常情况下,时间复杂度为 O(M+N);O(M+N);

特点 三: 如果主串和子串存在多个零时,如:如果主串和子串存在多个零时,如:S=‘0000…1’{S=‘0000…1’{ 总共总共 5252 个零个零 }} ;; T=‘00000001’,T=‘00000001’,

则出现多次重复的比较,即出现不等时, 则出现多次重复的比较,即出现不等时, I I 指针每次都回朔到指针每次都回朔到 i-1i-1 位置,这位置,这样浪费了大量的比较时间,整个匹配需要回朔样浪费了大量的比较时间,整个匹配需要回朔 4545 次,次, WhileWhile 循环语句的执行循环语句的执行次数为次数为 46*846*8 (( index*mindex*m )) ..

Page 7: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

算法 4.5 Index(S,T,pos) Index(S,T,pos) 即模式匹配的时间复杂性分即模式匹配的时间复杂性分析析因为 Index(S,T,pos)Index(S,T,pos) 是是一种有回溯的模式匹配算法 ;所以,在最坏情况下的时间复杂度是 O(n*m) 。

Page 8: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

4. 3.2 模式匹配的一种改进算法模式匹配的一种改进算法模式匹配的一种改进算法是模式匹配的一种改进算法是 D.E.Knuth D.E.Knuth 与与 V.R.PrattV.R.Pratt 和和 J.H.MorrisJ.H.Morris 同时发现同时发现的,因此,称该算法为克努特的,因此,称该算法为克努特 -- 莫里斯莫里斯 -- 普拉特算法(简称为普拉特算法(简称为 KMPKMP 算法)。算法)。在串匹配算法中在串匹配算法中又称 KMP 模式匹配算法。KMP 算法优点:可以在 O(M+N) 的时间复杂度内完成模式匹配操作,即对Index(S,T,pos)Index(S,T,pos) 模式匹配算法的改进,取消了主串的回溯 。

KMP 算法基本思想:每当匹配过程中出现字符比较不等时, i 不回溯。

Page 9: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

i=3 , j=3 时,失败即s3 ≠ t3 ; ;S1=t1 ; s2=t2; 因为 t1≠t2; 所以 t1≠s2

a b a b c a b c a c b a bi

j

第第 11趟趟 a b c a c

a b a b c a b c a c b a b

a b c a c

第第 33趟趟

KMPKMP 模式匹配算法图示模式匹配算法图示 -1-1

Page 10: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

a b a b c a b c a c b a b

a b c a c

第第 33趟趟

i

j

i=7 , j=5 失败s4=t2;t1≠t2

∴t1≠s4

a b a b c a b c a c b a b

a b c a c

第第 44趟趟

KMPKMP 模式匹配算法图示模式匹配算法图示 -2-2

Page 11: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

a b a b c a b c a c b a b

a b c a c

第第 33趟趟

i

j

i=7 , j=5 失败s5=t3;t1≠t3

∴t1≠s5

a b a b c a b c a c b a b

a b c a c

第第 55趟趟

KMPKMP 模式匹配算法图示模式匹配算法图示 -3-3

Page 12: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

a b a b c a b c a c b a b

a b c a c

第第 33趟趟

i

j

i=7 , j=5 失败s5=t3;t1≠t3

∴t1≠s5

匹配成功a b a b c a b c a c b a b

a b c a c

第第 66趟趟

KMPKMP 模式匹配算法图示模式匹配算法图示 -4-4

Page 13: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

KMPKMP 模式匹配算法小结模式匹配算法小结 -1-1(( 11 )结论: )结论: ii 可以不回溯可以不回溯,模式向右滑动到的新,模式向右滑动到的新比较起点比较起点 k k ,并且,并且 k k 仅与模式串仅与模式串 TT 有关!有关!(( 22 )需要讨论两个问题:)需要讨论两个问题:

①① 如何由当前部分匹配结果确定模式向右滑动的新比较如何由当前部分匹配结果确定模式向右滑动的新比较起点起点 kk ??②② 模式应该向右滑多远才是最高效率的模式应该向右滑多远才是最高效率的 ??

Page 14: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

(( 11 )模式滑动到第)模式滑动到第 kk 个字符,有个字符,有 pp11 ~~ ppkk-1-1 == SSii-(-(kk-1)-1) ~~ SSii-1-1 (( 22 )再观察失配时,有)再观察失配时,有 ppjj-(-(kk-1) -1) ~~ ppjj-1 -1 == SSii-(-(kk-1) -1) ~~ SSii-1-1

两式联立可得: pp11 ~~ ppkk-1-1 == ppjj-(-(kk-1)-1) ~~ ppjj-1-1

pp==""a ba b cc a a a ba b a a b cb c""

S=S=""a b a b ca b a b c aa a ba b cc c b a b c b a b""i

jSi- ( k - 1 ) ... si-1

P1 --pk-1

Pj-(k-1) Pj-1

当 si ≠ pj 失匹时

Page 15: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

S=S=""a b a b ca b a b c aa a ba b cc c b a b c b a b""i

j

S="a b a b cS="a b a b c a a aa bb cc c b a b" c b a b"pp==""a ba b cc a c a c""

i

kpp==""a ba b cc a a a ba b a b c a b c""

关注部分匹配时的关注部分匹配时的重要重要特征特征————KMPKMP 模式匹配算法小结模式匹配算法小结 -2-2

假设:主串为假设:主串为’’ SS11SS22 ,,……,, SSnn’’模式串为模式串为’’ pp11,p,p22,…,p,…,pnn’’当匹配过程中,产生失配(即当匹配过程中,产生失配(即 si<> pjsi<> pj )时,模式串“向右滑动多远)时,模式串“向右滑动多远??””即主串中第即主串中第 ii 个字符(个字符( ii 指针不指针不回溯回溯)应与模式串中哪个字符再)应与模式串中哪个字符再比较?比较?

Page 16: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

模式滑动到第模式滑动到第 kk 个字符,有个字符,有 pp11 ~~ ppkk-1-1 == SSii-(-(kk-1)-1) ~~ SSii-1-1 …(4-2)…(4-2)而已经得到的“部分匹配”的结果是:而已经得到的“部分匹配”的结果是: ppjj-(-(kk-1) -1) ~~ ppjj-1 -1 == SSii-(-(kk-1) -1) ~~ SSii-1 -1 …(4-3) …(4-3)

将将 (4-2) (4-2) 和和 (4-3)(4-3) 两式联立可得: pp11 ~~ ppkk-1-1 == ppjj-(-(kk-1)-1) ~~ ppjj-1 -1 …(4-4)…(4-4)

假设:这时应与模式串中第假设:这时应与模式串中第 kk 个(个( k<jk<j ) 个字符继续比较,则模式) 个字符继续比较,则模式串中第串中第 k-1k-1 个字符的子串必须满足下列关系式(教材个字符的子串必须满足下列关系式(教材 P81P81 的的 4-24-2 )),且不可能存在,且不可能存在 k’>kk’>k 满足下列关系式(满足下列关系式( 4-24-2 ):):

反之,若模式串中存在满足式(反之,若模式串中存在满足式( 4-44-4 )的两个子串,则当匹配过程中,主串第)的两个子串,则当匹配过程中,主串第I I 个字符与模式串中第个字符与模式串中第 j j 个字符比较不等时,仅需将模式向右滑动至模式中个字符比较不等时,仅需将模式向右滑动至模式中第第 kk 个字符和主串中第个字符和主串中第 ii 个字符对齐,这时,模式串中个字符对齐,这时,模式串中 k-1k-1 个字符‘个字符‘ pp11 ~~ ppkk-1-1 ’’ 必定与主串中第必定与主串中第 ii 个字符之前的个字符之前的 k-1k-1 的子串‘的子串‘ SSi-(k-1)i-(k-1) ~~ SSi-1i-1 ’ 相等,因此,匹配仅需从第第 kk 个字符与主串中第个字符与主串中第 ii 个字符比较起继续进行。个字符比较起继续进行。

Page 17: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

pp11…p…pkk-1-1 == ppjj-(-(kk-1)-1) …p …pjj-1-1 说明了什么?说明了什么?(( 11 ) ) kk 与与 jj 具有函数关系,具有函数关系,由当前失配位置 由当前失配位置 j j ,可以计算,可以计算出出滑动位置 滑动位置 kk (即比较的(即比较的新起点)新起点);;(( 22 ))滑动位置滑动位置 kk 仅与模式串仅与模式串 TT 有关有关。。

从第 1 位往右经过 k-1 位 从 j-1 位往左经过 k-1 位kk == max { max { kk |1< |1<kk<<jj 且且 pp11…p…pkk-1-1 == ppjj-(-(kk-1)-1) …p …pjj-1-1 } }

pp11…p…pkk-1-1 == ppjj-(-(kk-1)-1) …p …pjj-1-1 的物理意义是什么?的物理意义是什么?

模式应该向右滑多远才是最高效率的模式应该向右滑多远才是最高效率的 ??

KMPKMP 模式匹配算法小结模式匹配算法小结 -3-3

Page 18: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

next[ j ]next[ j ] ==0 0 当当 jj == 11 时 时 //// 不比较不比较max { k | 1<k<j max { k | 1<k<j 且且 pp11…p…pk-1k-1=p=pj-(k-1)j-(k-1) …p …pj-1j-1 } }

1 1 其他情况其他情况

令令 k = next[ j ]k = next[ j ] ,则:,则:

next[j]next[j] 函数表征着模式函数表征着模式 TT 中最大相同首子串和尾子串(真子串)的长度。中最大相同首子串和尾子串(真子串)的长度。可见,可见,模式中相似部分越多,则模式中相似部分越多,则 next[j]next[j] 函数越大函数越大,它既表示模式 ,它既表示模式 T T 字符字符

之间的相关度越高,模式串向右滑动得越远,与主串进行比较的次数越少,时间之间的相关度越高,模式串向右滑动得越远,与主串进行比较的次数越少,时间复杂度就越低。复杂度就越低。

KMPKMP 模式匹配算法小结模式匹配算法小结 -4-4

Page 19: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

KMPKMP 模式匹配算法中模式匹配算法中 next[j]next[j] 的计算方法的计算方法 计算计算 next[j]next[j] 的方法: 的方法:

当当 j=1j=1 时,时, next[j]=0next[j]=0 ;; //next[j]=0//next[j]=0 表示根本不进行字表示根本不进行字符比较符比较 当当 j>1j>1 时,时, next[j]next[j] 的值为:模式串的位置从的值为:模式串的位置从 11 到到 j-1j-1构成的串中所出现的首尾相同的子串的最大长度加构成的串中所出现的首尾相同的子串的最大长度加 11 。。 当无首尾相同的子串时当无首尾相同的子串时 next[j]next[j] 的值为的值为 11 。。 next[j]=1next[j]=1表示从模式串头部开始进行字符比较表示从模式串头部开始进行字符比较

Page 20: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

KMP算法的时间复杂度可达到KMP算法的时间复杂度可达到 O(m+n)O(m+n)其改进在于:每当一趟匹配过程中出现字符比较不等时,其改进在于:每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。比较。在下面将要解决的问题是:如何求出下一个在下面将要解决的问题是:如何求出下一个 jj 的位置即的位置即next[j]=?next[j]=? ,而不,而不回溯i指针。回溯i指针。

Page 21: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

目前需要解决的问题是—— ( 1 )若 i 不需回溯,则 j 应该退回到何处?( 2 )设退回到 next[j] , 则 next[j]= ?( 3 )对于给定的模式串,如何求解 next[j] 是问题的关键。( 4 ) next[j] 与 s 串无关,只与 t 串有关

Page 22: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

0 当 j=1

max { k | 1< k < j 且 “p1p2 …pk1 " =“pjk+1 pjk+2 …pj1 " }

( 相同的前缀子串与后缀子串的最大长度 +1)1 其他

Next [ j ]=

Next [ j ] 函数定义和计算模式如下:

Page 23: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

例 : 设有模式串 T=“abaabcac“, 计算 next[j]

j 1 2 3 4 5 6 7 8模式串 a b a a b c a c next[j] 0 1 1 2 2 3 1 2

Page 24: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

int Index_KMP(SString S, SString T, int pos) { // 1≤pos≤StrLength(S) i = pos; j = 1; while (i <= S[0] && j <= T[0]) { if (j == 0 || S[i] == T[j]) { ++i; ++j; } // 继续比较后继字符 else j = next[j]; // 模式串向右移动 } if (j > T[0]) return i-T[0]; // 匹配成功 else return 0;} // Index_KMP

算法 4.6 P82

主串 S=“acabaabaabcacaabc”

模式串 T=“abaabc”

Page 25: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

begin

(j > T[0])?

end

return i-T[0]

i <= S[0] && j <= T[0])?y

i = pos; j = 1;

(j == 0 || S[i] == T[j])?y

i=i+1 ; j=j+1;

N

N

j = next[j]

N

y

返回0

Page 26: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

KMP算法是在已知模式串的 next函数值的基础上执行的,那么,如何求得模式串的 next函数值呢? 从上述讨论可见: k k 的确定方法的确定方法 当比较到模式第 当比较到模式第 j j 个字符失配时个字符失配时 ,, k k ( next[j] )( next[j] ) 的值的值与模式的前 与模式的前 j j 个字符有关,与目标无关。个字符有关,与目标无关。此函数值仅取决于模式串本身而和相匹配的主串无关。我们可从分析其定义出发用递推的方法求得 next 函数值。

Page 27: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

求 next函数值的过程是一个递推过程,分析如下-1 :已知 : next[1] = 0;    (4-6)假设 : next[j] = k ;     有 : ‘P1P2……Pk-1‘=‘Pj-k+1Pj-k+2……Pj-1’  (4-7)其中 k 为满足1 <k<j 的某个值,且不可能存在 k’>k 满足等式 (4-7) 。这时,

next[j] = ? 可能存在两种情况:情况一: 若 : Pk = Pj  ,则表明在模式串中存在, ‘P1P2……Pk ‘=‘Pj-k+1Pj-k+2……Pj ’ (4-8)且不可能存在 k’>k 满足等式 (4-8) ,也就是说 next[j+1] = k + 1 ,即      next[j+1] = next[j] + 1 = k + 1情况二: Pk <> Pj , 则表明在模式串中     ‘ P1P2……Pk ’ < > ‘Pj-k+1Pj-k+2……Pj ’这时,可将求 next 函数值问题看作是一个模式匹配问题,整个模式串既是主串又是模式串。而当前在匹配过程中,已经有:

Page 28: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

求 next函数值的过程是一个递推过程,分析如下-2 :有 : ‘Pj-k-1‘=‘P1’  , Pj-k-2 = P2  ,‘ Pj-1 ‘=‘Pk’ 则当 Pk <> Pj 时 , 应将模式向右滑动至模式中的第 next[k] 个字符和主串中第 j 个字符相比较。若

next[k]=k’ ,且 pj=pk’, 则说明在主串中第 j+1 个字符之前存在一个长度为 k’ (即 next[k] 最长子串,和模式串中从首字符起长度为 k’ 的子串相等,即( P83 )     有 : ‘P1P2……Pk’‘=‘Pj-k’…, Pj’  ( 1<k’<k<j) (4- 10 ) 就是说, next[j+1]=k’+1 ( 4-11 )同理,若 Pj <> Pk’ ,则将模式继续向右滑动直至将模式 next[k’] 个字符和 pj 对齐,…,以此类推,直至 pj 和模式中某个字符匹配成功或者不存在任何 k’(1<k’<j) 满足等式 (4-10) ,则 next [j+1] = 1 ( 4-12 )

Page 29: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

  根据下边的图 4.6 中的模式串,已经求出前 6 个字符的 next 函数值,现求 next[7] =? ,

因为 next[6]=3 ,又因 p6<>p3,

则需比较 p6 和 p1 (因为 next[ 3 ]= 1,这相当于将子串模式向右滑动,由于 p6<>p1 , 而且 next[1]=0 ,所以, next[7]= 1,而 p7=p1 , 则 next[8]=2。

Page 30: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

模式串的匹配过程模式串的匹配过程 j=5 j+1=6

目标目标 a bb a a b c a c模式 模式 a b a

0 1 1 2 2 3

设 next[j]=k j=5,k=2则 next[5]=2P1 …Pk-1 = Pj-k+1 … Pj-1

P1 = P4若 (1)Pj = Pk

P2 = P5

有 P1 P2 = P4 P5

(P1 …Pk-1 = Pj-k+1 … Pj-1) j-1=5 ∴j=6 k-1=2 next[6]=3 next[j+1]= next[j]+1 = k+1

J=5 J+1=6

下面再用图示法举例说明求 next函数值的匹配过程:

Page 31: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

这实际上也是一个匹配的过程 ;不同在于:部分主串和模式串是同一个串

求 next函数值的过程是一个递推过程,分析如下 :

已知 : next[1] = 0;假设 : next[j] = k ;有 : ‘P1P2……Pk-1‘=‘Pj-k+1Pj-k+2……Pj-1‘(2) 若 : Pj Pk

则 : 需往前回朔,检查 Pj= P ?

Page 32: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

综上所述,根据分析结果式 (4-6) 、 (4-9) 、 (4-11) 和 (4-12) ,仿照 KMP 算法,可以求出 next 函数值的算法,如算法 4.7 ( p83 )所示: void get_next(SString &T, int &next[] ) { // 求模式串 T 的 next 函数值并存入数组 next i = 1; next[1] = 0; j = 0; while (i < T[0])    { if (j = 0 || T[i] == T[j]) {++i; ++j; next[i] = j; } else j = next[j];   } } // get_next

算法 4.7 的时间复杂度为  O ( m ),通常模式串的长度要比主串的长度 n 要小得多,因此,对整个匹配算法来讲,所增加的这点时间是值得的。

Page 33: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

还有一种特殊情况需要考虑:例如: S = aaabaaaab T = aaaab

nextval[j]=00004next[j]=01234

Page 34: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

void get_nextval(SString &T, int &nextval[]) { i = 1; nextval[1] = 0; j = 0; while (i < T[0]) { if (j = 0 || T[i] == T[j]) { ++i; ++j; if (T[i] != T[j]) next[i] = j; else nextval[i] = nextval[j]; } else j = nextval[j]; } } // get_nextval

Page 35: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

4. 4 串操作应用举例串操作应用举例 4. 4.1 文本编辑文本编辑 4. 4.2 建立词索引表建立词索引表

Page 36: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

4. 4.1 文本编辑文本编辑 为了管理文本串中的页和行,在文本编辑时,编辑软件先为文本串建立相应的页表和行表,页表的每一项列出页号和该页的起始行号,行表的每一项则指示每一行的行号、起始地址和该行子串的长度。行表和页表与串是分开存储的。

Page 37: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

将如下一段源程序中的每行语句的起始地址和长度信息存储在100 开始的地址中;具体的源程序存放在 201 开始的内存中:Main(){

float a,b,max;

scanf(“%f,%f”,&a,&b);

if a>b max=a;

else max=b;

}

Page 38: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

m a i n ( ) { f l o a t a , b ,

m a x ; s c a n f ( “ % f , % f ”

, & a , & b ) ; i f a > b m

a x = a ; e l s e m a x = b ;

}

201

行号 起始地址 长度100 201 8

101 209 17

102 226 24

103 250 17

104 267 15

105 282 2

Page 39: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

4. 4.2 建立词索引表 建立词索引表 p86p86

具体步骤:( 1 )建立图书的书号及书名表的数据结构;( 2 )根据图书名中的关键词,建立书号索引及对应的的数据结构;( 3 )从图书文件中读入一个书目串;( 4 )从目串中提取所有关键词插入词表;( 5 )对词表的每一个关键词,在索引表中进行查找,并作相应的插入操作。重复上述的( 3 )、( 4 )和( 5 )。具体算法见 P87-89 。

Page 40: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

1 、 熟悉串基本操作的定义,并能利用这些基本操作来实现串的其它各种操作的方法。 2 、 熟练掌握在串的定长顺序存储结构上实现串的各种操作的方法。 3 、了解串的堆存储结构以及在其上实现串操作的基本方法。

第四章学习要点

Page 41: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

4、理解串匹配的 KMP算法,熟悉 NEXT函数的定义,学会手工计算给定模式串的NEXT函数值和改进的 NEXT函数值。5 、了解串操作的应用方法和特点。

Page 42: 这是串的一种重要操作,很多软件,若有 “ 编辑 ” 菜单项的话,则其中必有 “ 查找 ” 子菜单项。

第四章结束