知识点串的模式匹配
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
pj-(k-1) ~ pj-1 =Si-(k-1) ~ Si-1 …(4-3) 将(4-2) 和(4-3)两式联立可得:p1~pk-1=pj-(k-1) ~pj-1 …(4-4)
反之,若模式串中存在满足式(4-4)的两个子串,则当匹配过程中,主串第I 个字符与模式串中第j 个字符比较不等时,仅需将模式向右滑动至模式中第k 个字符和主串中第i个字符对齐,这时,模式串中k-1个字符‘p1~pk-1 ’必定 与主串中第i个字符之前的k-1的子串‘Si-(k-1) ~ Si-1 ’ 相等,因此,匹配仅需 从第k个字符与主串中第i个字符比较起继续进行。
Pj-1
当 si ≠ pj失匹时
2020/6/18
小结-2
关注部分匹配时的重要特征——
i
S="ap=b"aa
b b
c c
a a
a a
b b
cc b a a b c"
b"
j
i
S="a b a b cpa="aabbcccabca"b"
k
假设:主串为’S1S2,…,Sn’ 模式串为’p1,p2,…,pn’ 当匹配过程中,产生失配(即si<> pj)时,模式串“向右滑动多 远?”即主串中第i个字符(i指针不回溯)应与模式串中哪个字符再 比较20?20/6/18
∴t1≠s5
j
第 aba
6 趟
2020/6/18
bcab ca cb ab a b c a c 匹配成功
KMP模式匹配算法小结-1
(1)结论: i可以不回溯 ,模式向右滑动到的新比 较起点k ,并且k 仅与模 式串T有关!
2020/6/18
(1)模式滑动到第k个字符,有p1~pk-1 =Si-(k-1) ~ Si-1
从第1位往右 经过k-1位
从j-1位往左 经过k-1位
模式应该向右滑多远才是最高效率的?
2k0=20/m6/a1x8 { k |1<k<j 且p1…pk-1=pj-(k-1) …pj-1 }
小结-4
令k = next[ j ],则:
next[ j ]=
0 当j=1时 //不比较 max { k | 1<k<j 且p1…pk-1=pj-(k-1) …pj-1 } 1 其他情况
2020/6/18
p79算法4.5
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; } // 2In0d2e0x/6/18
特点 三: 如果主串和子串存在多个零时,如: S=‘0000…1’{总共52个零};T=‘00000001’, 则出现多次重复的比较,即出现不等时, I 指针每次都回朔到i-1位置,这样 浪费了大量的比较时间,整个匹配需要回朔45次,While循环语句的执行次 数为46*8(index*m).
2020/6/18
例如:对某文本进行编辑时,可以运用如下步骤: (1)编辑;(2)查找 ——“输入查找文本(字符串)”;(3)找出对应 的串
2020/6/18
T串
defghijk
pos=4
Abcdefghijklmnopqrstuvw
S串
按照上述主串S和子串T求子串位置的定位函数 Index(S,T,pos)的返回值是4
(2)再观察失配时,有pj-(k-1) ~ pj-1 =Si-(k-1) ~ Si-1
两式联立可得:p1~pk-1=pj-(k-1) ~pj-1
i
S="a b a b c a a b c c b a b"
Si-(k-1)... si-1
j
p="a b c a a b a b c"
P1 --pk-1
Pj-(k-1)
第 aba b cabc a cbab
3 趟
2020/6/18
abc ac
KMP模式匹配算法图示-2
i
第 aba bca bcac ba b
3
趟
abc ac
i=7,j=5失败s4=t2;t1≠t2
∴t1≠s4
j
第 ab ab cabc acba b
4 趟
2020/6/18
abc ac
KMP模式匹配算法图示-3
2020/6/18
求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] = ?
• 计算next[j]的方法:
– 当j=1时,next[j]=0; //next[j]=0表示根本不进行 字符比较
– 当j>1时,next[j]的值为: 2020/6/18 模式串的位置从1到j-1构
KMP算法的时间复杂度可达到O(m+n) 其改进在于:每当一趟匹配过程中出现字符比较不等时, 不需回溯i指针,而是利用已经得到的“部分匹配”的结 果将模式向右“滑动”尽可能远的一段距离后,继续进行 比较。 在下面将要解决的问题是:如何求出下一个j的位置即 next[j]=?,而不回溯i指针。
假设:这时应与模式串中第k个(k<j) 个字符继续比较,则模式串 中第k-1个字符的子串必须满足下列关系式(教材P81的4-2),且不 可能存在k’>k满足下列关系式(4-2):
模式滑动到第k个字符,有p1~pk-1 =Si-(k-1) ~ Si-1 …(4-2) 而已经得到的“部分匹配”的结果是:
2020/6/18
目前需要解决的问题是—— (1)若i不需回溯,则 j应
该退回到何处?
(2)设退回到 next[j], 则next[]=?2020/6/18
Next [ j ]函数定义和计算模式如下:
0
当 j=1
Next [ j ]= 2020/6/18
max { k | 1< k < j 且
“p1p2 …pk1 " =“pjk+1 pjk+2 …pj1 "}
(相同的前缀子串与后缀子串的最大长度+1)
1
其他
例:
• 设有模式串 T=“abaabcac“, 计算next[j]
2020/6/18
算法4.6 P82
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;
2020/6/18
KMP模式匹配算法小结-3
p1…pk-1=pj-(k-1) …pj-1说明了什么? (1) k 与 j 具有函数关系,由当前失配位置 j ,可以计算出滑
动位置 k(即比较的新起点);
(2)滑动位置k 仅与模式串T有关。 p1…pk-1=pj-(k-1) …pj-1的物理意义是什么?
next[j]函数表征着模式T中最大相同首子串和尾子串(真子串)的长度。 可见,模式中相似部分越多,则next[j]函数越大,它既表示模式 T 字符之 间的相关度越高,模式串向右滑动得越远,与主串进行比较的次数越少,时间复 杂度就越低。
2020/6/18
KMP模式匹配算法中next[j]的计算方法
i
第 ababcabcacbab
3
趟
abc ac
i=7,j=5失败s5=t3;t1≠t3
∴t1≠s5
j
第 aba
5 趟
2020/6/18
bc a bcacba b abc a c
KMP模式匹配算法图示-4
i
第 ab abca bcac bab
3
趟
ab cac
i=7,j=5失败s5=t3;t1≠t3
N
(j > T[0])?
y
return i-T[0]
end
N返 回0
2020/6/18
KMP算法是在已知模式串的next函数值的基础上执行 的,那么,如何求得模式串的next函数值呢? 从上述讨 论可见:
k 的确定方法 当比较到模式第 j 个字符失配时, k ( next[j] ) 的值与模 式的前 j 个字符有关,与目标无关。 此函数值仅取决于模式串本身而和相匹配的主串无关。 我们可从分析其定义出发用递推的方法求得next函数值。
• 4. 3 串的模式匹配算法( 知识点三) • 子串定位运算又称为模式匹配或串匹配,此运算的应
用非常广泛。例如,文本编辑程序中,经常要查找某 一特定单词出现的位置。解此问题的有效算法能极大 地提高文本编辑程序的响应性能。 串的模式匹配定义:在主串中寻找子串在串中的位置。 在模式匹配中,子串称为模式串,主串称为目标串。
可能存在两种情况:
情况一: 若: 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 , 则表明在模式串中
主串s="ababcabcacbab",模式T="abcac"
主串s
模式串T ="abcac" 模式串T ="abcac"
模式串T ="abcac"
核心语句
if
(Se[2il]s0e=2={0Ti =/[6j]i)/-1j{+8+2+; i;j
++j; = 1;
} }
// 继续比较后继字符
i=6 返回值为11-5=6
算法4.5 Index(S,T,pos) 即模式匹配的时间复杂性分析 因为Index(S,T,pos)是一种有回溯的模式匹配算法 ; 所以,在最坏情况下的时间复杂度是O(n*m)。
2020/6/18
• 4. 3.2 模式匹配的一种改进算法
模式匹配的一种改进算法是D.E.Knuth 与V.R.Pratt和J.H.Morris同时发现的, 因此,称该算法为克努特-莫里斯-普拉特算法(简称为KMP算法)。在串匹 配算法中又称 KMP模式匹配算法。
这是串的一种重要操作,很多软件,若有“编辑”菜单 项的话,则其中必有“查找”子菜单项。
2020/6/18
• 4. 3.1 求子串位置的定位函数 Index(S,T,pos)
Index(S,T,pos)称为模式匹配(S为主串, T为模式串 ); 初始条件:S和T存在,T是非空串, 1 <= pos <= (S的长度)。 操作结果:若主串S中存在和串T相同的(模式串 )子串,则返回它在 主串S中第pos个字符之后第一次出现的位置;否则返回0。
i=11
b
J=6
算法4.5 Index(S,T,pos) 即模式匹配的特点:
特点一: Index(S,T,pos) 算法的匹配方法简单,理解方便,适合一些文本编辑,效 率较高;
特点二: Index(S,T,pos) 算法的匹配方法简单,理解方便,适合一些文本编辑,效 率较高;正常情况下,时间复杂度为O(M+N);
KMP算法优点:可以在O(M+N)的时间复杂度内完成模式匹配操作,即对 Index(S,T,pos)模式匹配算法的改进,取消了主串的回溯 。
KMP算法基本思想:每当匹 20配20/6/1过8 程中出现字符比较不
KMP模式匹配算法图示-1
i
第 aba bc abcac bab
1
趟 abc ac
j
i=3,j=3时,失败即 s3 ≠ t3 ;; S1=t1 ; s2=t2; 因为t1≠t2;所以t1≠s2
} // Index_KMP
主串S=“acabaabaabcacaabc”
模式2串0T2=0“/a6b/a1a8bc”
N
j = next[j]
begin
i = pos; j = 1;
i <= S[0] && j <= T[0])?
y
(j == 0 || S[i] == T[j])?
y i=i+1 ; j=j+1;
反之,若模式串中存在满足式(4-4)的两个子串,则当匹配过程中,主串第I 个字符与模式串中第j 个字符比较不等时,仅需将模式向右滑动至模式中第k 个字符和主串中第i个字符对齐,这时,模式串中k-1个字符‘p1~pk-1 ’必定 与主串中第i个字符之前的k-1的子串‘Si-(k-1) ~ Si-1 ’ 相等,因此,匹配仅需 从第k个字符与主串中第i个字符比较起继续进行。
Pj-1
当 si ≠ pj失匹时
2020/6/18
小结-2
关注部分匹配时的重要特征——
i
S="ap=b"aa
b b
c c
a a
a a
b b
cc b a a b c"
b"
j
i
S="a b a b cpa="aabbcccabca"b"
k
假设:主串为’S1S2,…,Sn’ 模式串为’p1,p2,…,pn’ 当匹配过程中,产生失配(即si<> pj)时,模式串“向右滑动多 远?”即主串中第i个字符(i指针不回溯)应与模式串中哪个字符再 比较20?20/6/18
∴t1≠s5
j
第 aba
6 趟
2020/6/18
bcab ca cb ab a b c a c 匹配成功
KMP模式匹配算法小结-1
(1)结论: i可以不回溯 ,模式向右滑动到的新比 较起点k ,并且k 仅与模 式串T有关!
2020/6/18
(1)模式滑动到第k个字符,有p1~pk-1 =Si-(k-1) ~ Si-1
从第1位往右 经过k-1位
从j-1位往左 经过k-1位
模式应该向右滑多远才是最高效率的?
2k0=20/m6/a1x8 { k |1<k<j 且p1…pk-1=pj-(k-1) …pj-1 }
小结-4
令k = next[ j ],则:
next[ j ]=
0 当j=1时 //不比较 max { k | 1<k<j 且p1…pk-1=pj-(k-1) …pj-1 } 1 其他情况
2020/6/18
p79算法4.5
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; } // 2In0d2e0x/6/18
特点 三: 如果主串和子串存在多个零时,如: S=‘0000…1’{总共52个零};T=‘00000001’, 则出现多次重复的比较,即出现不等时, I 指针每次都回朔到i-1位置,这样 浪费了大量的比较时间,整个匹配需要回朔45次,While循环语句的执行次 数为46*8(index*m).
2020/6/18
例如:对某文本进行编辑时,可以运用如下步骤: (1)编辑;(2)查找 ——“输入查找文本(字符串)”;(3)找出对应 的串
2020/6/18
T串
defghijk
pos=4
Abcdefghijklmnopqrstuvw
S串
按照上述主串S和子串T求子串位置的定位函数 Index(S,T,pos)的返回值是4
(2)再观察失配时,有pj-(k-1) ~ pj-1 =Si-(k-1) ~ Si-1
两式联立可得:p1~pk-1=pj-(k-1) ~pj-1
i
S="a b a b c a a b c c b a b"
Si-(k-1)... si-1
j
p="a b c a a b a b c"
P1 --pk-1
Pj-(k-1)
第 aba b cabc a cbab
3 趟
2020/6/18
abc ac
KMP模式匹配算法图示-2
i
第 aba bca bcac ba b
3
趟
abc ac
i=7,j=5失败s4=t2;t1≠t2
∴t1≠s4
j
第 ab ab cabc acba b
4 趟
2020/6/18
abc ac
KMP模式匹配算法图示-3
2020/6/18
求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] = ?
• 计算next[j]的方法:
– 当j=1时,next[j]=0; //next[j]=0表示根本不进行 字符比较
– 当j>1时,next[j]的值为: 2020/6/18 模式串的位置从1到j-1构
KMP算法的时间复杂度可达到O(m+n) 其改进在于:每当一趟匹配过程中出现字符比较不等时, 不需回溯i指针,而是利用已经得到的“部分匹配”的结 果将模式向右“滑动”尽可能远的一段距离后,继续进行 比较。 在下面将要解决的问题是:如何求出下一个j的位置即 next[j]=?,而不回溯i指针。
假设:这时应与模式串中第k个(k<j) 个字符继续比较,则模式串 中第k-1个字符的子串必须满足下列关系式(教材P81的4-2),且不 可能存在k’>k满足下列关系式(4-2):
模式滑动到第k个字符,有p1~pk-1 =Si-(k-1) ~ Si-1 …(4-2) 而已经得到的“部分匹配”的结果是:
2020/6/18
目前需要解决的问题是—— (1)若i不需回溯,则 j应
该退回到何处?
(2)设退回到 next[j], 则next[]=?2020/6/18
Next [ j ]函数定义和计算模式如下:
0
当 j=1
Next [ j ]= 2020/6/18
max { k | 1< k < j 且
“p1p2 …pk1 " =“pjk+1 pjk+2 …pj1 "}
(相同的前缀子串与后缀子串的最大长度+1)
1
其他
例:
• 设有模式串 T=“abaabcac“, 计算next[j]
2020/6/18
算法4.6 P82
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;
2020/6/18
KMP模式匹配算法小结-3
p1…pk-1=pj-(k-1) …pj-1说明了什么? (1) k 与 j 具有函数关系,由当前失配位置 j ,可以计算出滑
动位置 k(即比较的新起点);
(2)滑动位置k 仅与模式串T有关。 p1…pk-1=pj-(k-1) …pj-1的物理意义是什么?
next[j]函数表征着模式T中最大相同首子串和尾子串(真子串)的长度。 可见,模式中相似部分越多,则next[j]函数越大,它既表示模式 T 字符之 间的相关度越高,模式串向右滑动得越远,与主串进行比较的次数越少,时间复 杂度就越低。
2020/6/18
KMP模式匹配算法中next[j]的计算方法
i
第 ababcabcacbab
3
趟
abc ac
i=7,j=5失败s5=t3;t1≠t3
∴t1≠s5
j
第 aba
5 趟
2020/6/18
bc a bcacba b abc a c
KMP模式匹配算法图示-4
i
第 ab abca bcac bab
3
趟
ab cac
i=7,j=5失败s5=t3;t1≠t3
N
(j > T[0])?
y
return i-T[0]
end
N返 回0
2020/6/18
KMP算法是在已知模式串的next函数值的基础上执行 的,那么,如何求得模式串的next函数值呢? 从上述讨 论可见:
k 的确定方法 当比较到模式第 j 个字符失配时, k ( next[j] ) 的值与模 式的前 j 个字符有关,与目标无关。 此函数值仅取决于模式串本身而和相匹配的主串无关。 我们可从分析其定义出发用递推的方法求得next函数值。
• 4. 3 串的模式匹配算法( 知识点三) • 子串定位运算又称为模式匹配或串匹配,此运算的应
用非常广泛。例如,文本编辑程序中,经常要查找某 一特定单词出现的位置。解此问题的有效算法能极大 地提高文本编辑程序的响应性能。 串的模式匹配定义:在主串中寻找子串在串中的位置。 在模式匹配中,子串称为模式串,主串称为目标串。
可能存在两种情况:
情况一: 若: 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 , 则表明在模式串中
主串s="ababcabcacbab",模式T="abcac"
主串s
模式串T ="abcac" 模式串T ="abcac"
模式串T ="abcac"
核心语句
if
(Se[2il]s0e=2={0Ti =/[6j]i)/-1j{+8+2+; i;j
++j; = 1;
} }
// 继续比较后继字符
i=6 返回值为11-5=6
算法4.5 Index(S,T,pos) 即模式匹配的时间复杂性分析 因为Index(S,T,pos)是一种有回溯的模式匹配算法 ; 所以,在最坏情况下的时间复杂度是O(n*m)。
2020/6/18
• 4. 3.2 模式匹配的一种改进算法
模式匹配的一种改进算法是D.E.Knuth 与V.R.Pratt和J.H.Morris同时发现的, 因此,称该算法为克努特-莫里斯-普拉特算法(简称为KMP算法)。在串匹 配算法中又称 KMP模式匹配算法。
这是串的一种重要操作,很多软件,若有“编辑”菜单 项的话,则其中必有“查找”子菜单项。
2020/6/18
• 4. 3.1 求子串位置的定位函数 Index(S,T,pos)
Index(S,T,pos)称为模式匹配(S为主串, T为模式串 ); 初始条件:S和T存在,T是非空串, 1 <= pos <= (S的长度)。 操作结果:若主串S中存在和串T相同的(模式串 )子串,则返回它在 主串S中第pos个字符之后第一次出现的位置;否则返回0。
i=11
b
J=6
算法4.5 Index(S,T,pos) 即模式匹配的特点:
特点一: Index(S,T,pos) 算法的匹配方法简单,理解方便,适合一些文本编辑,效 率较高;
特点二: Index(S,T,pos) 算法的匹配方法简单,理解方便,适合一些文本编辑,效 率较高;正常情况下,时间复杂度为O(M+N);
KMP算法优点:可以在O(M+N)的时间复杂度内完成模式匹配操作,即对 Index(S,T,pos)模式匹配算法的改进,取消了主串的回溯 。
KMP算法基本思想:每当匹 20配20/6/1过8 程中出现字符比较不
KMP模式匹配算法图示-1
i
第 aba bc abcac bab
1
趟 abc ac
j
i=3,j=3时,失败即 s3 ≠ t3 ;; S1=t1 ; s2=t2; 因为t1≠t2;所以t1≠s2
} // Index_KMP
主串S=“acabaabaabcacaabc”
模式2串0T2=0“/a6b/a1a8bc”
N
j = next[j]
begin
i = pos; j = 1;
i <= S[0] && j <= T[0])?
y
(j == 0 || S[i] == T[j])?
y i=i+1 ; j=j+1;