Upload
yan-li
View
186
Download
5
Embed Size (px)
Citation preview
《数据结构( Java 版)(第 3 版)》
第 3 章 串
3.1 串抽象数据类型 3.2 串的表示和实现 3.3 串的模式匹配
《数据结构( Java 版)(第 3 版)》
目的和要求•目的:串作为特殊线性表的实现与应用。•内容:字符串的基本概念,串抽象数据类型,顺序
和链式两种存储结构存储串的特点;采用顺序存储结构实现串的各种操作算法;两种串的模式匹配算法及应用: Brute-Force 算法和 KMP 算法。
•要求:掌握顺序串类的基本操作实现方法,掌握串 的模式匹配算法及应用。
•重点:串数据类型的各种操作实现,两种串的模式 匹配算法及应用。
•难点: KMP 模式匹配算法, next 数组在 KMP算法中 的作用及产生过程。
•实验:顺序串类的基本操作及串的模式匹配算法。
《数据结构( Java 版)(第 3 版)》
3.1 串抽象数据类型3.1.1 串的基本概念1. 串定义。 s= " "
2. 子串。 "at"是 "data" 的子串。 3. 串比较。两个串可比较是否相等,也可比较大小。
110 nsss
《数据结构( Java 版)(第 3 版)》
public interface SString { int length(); // 返回串的长度 char charAt(int i) // 返回第 i( i≥0 )个字符 SString concat(SString str); // 返回与 str 串连接生成串 SString substring(int begin, int end); // 返回串中字符序号从 begin至 end-1 的子串 void setCharAt(int i, char ch) // 设置第 i 个字符为 ch SString insert(int i, SString str)// 在第 i 个字符处插入 str
串 SString delete(int begin, int end) // 删除从 begin到 end-1 的子串 int indexOf(SString pattern); // 返回模式串 pattern 在串中的首次匹配位置}
3.1.2 串抽象数据类型
《数据结构( Java 版)(第 3 版)》
3.2 串的表示和实现
3.2.1 串的存储结构3.2.2 字符串类 String
3.2.3 字符串类 StringBuffer
《数据结构( Java 版)(第 3 版)》
3.2.1 串的存储结构1. 串的顺序存储结构
2. 串的链式存储结构
(a)数组容量等于串长度,存储串常量
a b dcs
0
(b)数组容量大于串长度,存储串变量
length-1 length-11 …
s0 s1 sn-1…
s
1 2
s0 s1 sn-1…
a b d ec f
0 … len-1 …len
s2
s0
(a)单字符链表
data nexthead
s1 … sn-1 ∧
s0
(b)块链表
heads1 … si-1 si …si+1 ∧…
data[] next
… sn-1…
《数据结构( Java 版)(第 3 版)》
3.2.2 常量字符串类 String
1. String 类声明 public final class MyString implements
Comparable<MyString>,java.io.Serializ
able
{
private final char[] value;
// 字符数组,私有最终变量,只能赋值一次}
《数据结构( Java 版)(第 3 版)》
【例 3.1 】获得整数和实数字符串表示的数值。
整数
数字
+
-
实数
数字
+
- . 数字
E 数字
+
-e
《数据结构( Java 版)(第 3 版)》
2.连接串
a s2.valueb dc
b dc
x zy
x y z
s1.value
a
0 length-1
复制字符数组
… 0 length-1…
s3.value
1
buffer
《数据结构( Java 版)(第 3 版)》
3. 求子串
end-1 endbegin …
a b dc
d e
e gf
buffer
s.value
c
0 length-1… …
h
sub.value
《数据结构( Java 版)(第 3 版)》
4. 比较串相等与大小
《数据结构( Java 版)(第 3 版)》
5. String 串的插入、删除操作
( 1 )在 s1 串的 i 位置插入 s2 串
a b dc
d fe
x zy
x ya b
0 i length-1
+ +
…
s1.value e
…
z
s2.value
s3.value
f
i-1
c
《数据结构( Java 版)(第 3 版)》
( 2 )删除串中序号从 begin 至end-1 的子串
【例 3.2 】获得一个整数的二进制或十六进制形式字符串。
da e
+
end-1 endbegin …
a b yx
f
z eds3.value
b
0 length-1… …
f
s4.value
c
c
begin-1
《数据结构( Java 版)(第 3 版)》
3.2.3 变量字符串类StringBuffer
public final class MyStringBuffer implements java.io.Serializable
{ private char[] value; // 字符数
组 private int len; // 串长度}
《数据结构( Java 版)(第 3 版)》
1. 插入串
《数据结构( Java 版)(第 3 版)》
2. 删除子串
《数据结构( Java 版)(第 3 版)》
3.3 串的模式匹配
3.3.1 Brute-Force 算法3.3.2 KMP 算法
《数据结构( Java 版)(第 3 版)》
3.3.1 Brute-Force 算法1. Brute-Force 算法描述与实现
(a)第一次匹配,"t0t1t2"子串与模式串比较3次,匹配失败 (b)第二次匹配,"t1t2t3"子串与模式串比较1次,匹配失败
(c)若某次匹配失败,ti≠ pj,则下次匹配子串是"ti-j+1…ti+1" (d)若某次匹配成功,比较m次,匹配子串是"ti-m+1…ti"
a b b aa btarget
a b c
= ≠=
pattern
t0 t1 t2
p0 p1 p2
t3
c d
t5 t6 t7 t8
d
t4
a b b aa btarget
a b c
≠
pattern
t0 t1 t2
p0 p1 p2
t3
c dd
… tn-1
a b b aa btarget
a b c
≠
pattern
t0 … ti-j
p0 … pj
…
c dd
ti
= =
tn-1
a b b aa btarget
a b cpattern
t0 … ti-m+1
p0 … pm-1
…
c dd
ti
= = =
t5 t6 t7 t8t4
《数据结构( Java 版)(第 3 版)》
2.模式匹配应用( 1 )替换子串
a b a bd ctarget.value
0
a b
replacement x y
i
结果串
i+m
c
a b x yd a b c
与pattern匹配的子串+ +
… …i-1 n-1…i+m-1
《数据结构( Java 版)(第 3 版)》
( 2 )删除子串
a b a bd ctarget.value
0
a b
i
结果串
c
a b d a b c
与pattern匹配的子串+
… …i-1 …i+m n-1i+m-1
《数据结构( Java 版)(第 3 版)》
3. Brute-Force 算法分析 第1次匹配
(a)最好情况,"t0t1…tm-1"="p0p1…pm-1",比较次数为模式串长度m,时间复杂度为O(m)
=
(b)最坏情况,每次匹配比较m次,匹配n-m+1次,时间复杂度为O(n×m)
a b a bb atarget
a b b
= =
pattern
t0 tm-1 …
p0
tn-1
pm-1
=
t1
p0
…
…
≠
a a a aatarget
a a b
= =
pattern
≠
a a a aatarget
a a b
=
pattern
t0
p0
≠
a a a aatarget
a a b
=
pattern
a a a aatarget
a a b
=
pattern
= =
… tn-1tn-m+1
p0 pm-1… p0 pm-1…
p1 p2 p1 p2
t1 t2 t2 t3
第1次匹配 第2次匹配
第3次匹配 第4次匹配
t0
t1 tn-1t0 …t0 t1
t4t3 t4
tn-m
《数据结构( Java 版)(第 3 版)》
3.3.2 KMP 算法
1. 目标串不回溯
a b a bc btarget
a b b
= ≠=
pattern
t0 t1 t2 …
p0 p1
tn-1
p2
t3
(a)"t0t1t2"与"p0p1p2"匹配,t0=p0,t1=p1,t2≠ p2,若p0≠ p1,则t1≠ p0,下次匹配t2与p0开始比较
若p0≠ p1,则t1≠ p0
a b a bc btarget
a b b
≠
pattern
t0 t1 t2 …
p0 p1 p2
t3
a b a bc btarget
a b bpatter
n
t0 t1 t2 …
p0 p1 p2
t3
a a a bc btarget
a a b
= ≠=
pattern
t0 t1 t2 …
p0 p1 p2
t3
若p0=p1,则t1=p0
a a a bc btarget
a b bpattern
t0 t1 t2 …
p0 p1 p2
t3
a a a bc btarget
a a bpatter
n
t0 t1 t2 …
p0 p1 p2
t3= =
(b)"t0t1t2"与"p0p1p2"匹配,t0=p0,t1=p1,t2≠ p2,若p0=p1,则t1=p0,下次匹配t2与p1开始比较
t2=p0?
t2=p1?
tn-1 tn-1
tn-1 tn-1 tn-1
《数据结构( Java 版)(第 3 版)》
2. KMP 算法描述( a )( b )
《数据结构( Java 版)(第 3 版)》
2. KMP 算法描述( c )
《数据结构( Java 版)(第 3 版)》
2. KMP 算法描述( d )
《数据结构( Java 版)(第 3 版)》
3. 求 next 数组
表 3-1 模式串 "abcabc"的 next 数组 j 0 1 2 3 4 5
模式串 a b c a b c
" " 中最长相同前后缀子串的长度 k
1 0 0 0 1 2
0 1 1
1 0[ ]
0¡Ü £¼ ÇÒʹ" ... " " ... "µÄ× î´ó ÕûÊýk j k j
jnext j
k k j p p p p
4. KMP 算法实现
110 jppp
《数据结构( Java 版)(第 3 版)》
5. 计算 next 数组的递推算法
表3-2 模式串 "abcabdabcabcaa"的next 数组
"
j 0 1 2 3 4 5 6 7 8 9 10 11 12 13
模式串 a b c a b d a b c a b c a a
"p0…pj1"中最长相同的前后缀子串长
度 k
-1 0 0 0 1 2 0 1 2 3 4 5 3 4
pattern a d a a bcb b
p3p0
pj
pj-1pk-1 pj-k
已知相同的最长前后缀子串
pk
c a a
p13p2
a b c
p1 p8p5 p7 p9 p12p11
较短前缀子串 较短后缀子串pk
《数据结构( Java 版)(第 3 版)》
6. 改进 next 数组target
= ≠=
pattern
a c a a
c a
b
c
bb
b
b
=
t0 ti- j … …ti… ti-1
p0 pjpj-1
a b
pk-1 pj-k
= =
a b
pattern
a c a a
c a
b
c
bb
b
b
ti- j … …titi-1
p0 pjpj-1
a b
pk-1 pj-k
pk
pk
c
c
ti-k
ti-k
a b
tn-1
c
a b
tn-1
c
d
target
t0 …
a b d
(a)第3次匹配,当ti≠ pj时,next[j]=k,若pk=pj,则有ti≠ pk
target
pattern
a c a a
(b)第4次匹配,ti继续与pnext[k]比较
c a
b
c
bb
b
b
t0 … …ti
p0 pm-1
a b
p1
a d c a b
tn-1
c
ti+1
…
t1
若pk=pj,则ti≠ pk
≠
ti+1
ti+1
b
= =
《数据结构( Java 版)(第 3 版)》
6. 改进 next 数组 表 3-3 模式串 "abcabc" 改进的 next 数组
j 0 1 2 3 4 5
模式串 a b c a b c
"p0…pj1"中最长相同的前后缀子串长度 k
1 0 0 0 1 2
pk与 pj比较 ≠ ≠ = = =
改进的 next[j] 1 0 0 1 0 0
《数据结构( Java 版)(第 3 版)》
图 3-18 KMP 模式匹配过程( a ~b )
《数据结构( Java 版)(第 3 版)》
图 3-18 KMP 模式匹配过程( c ~e )
《数据结构( Java 版)(第 3 版)》
表 3-4 模式串 "abcabdabcabcaa"改进的next 数组
j 0 1 2 3 4 5 6 7 8 9 10 11 12 13
模式串 a b c a b d a b c a b c a a
串长 k -1 0 0 0 1 2 0 1 2 3 4 5 3 4
比较 ≠ ≠ = = ≠ = = = = = ≠ = ≠
改进的next[j]
-1 0 0 -1 0 2 -1 0 0 -1 0 5 -1 4
《数据结构( Java 版)(第 3 版)》
7.KMP 算法分析
≠
(a)t0=p0,t1=p1,t2≠ p2,比较3次,next[2]=1
a a a aatarget
a a b
= =
pattern
t2
p2
≠
a a a aatarget
a a b
=
pattern
(b)t2=p1,t3≠ p2,比较2次,next[2]=1
t0
p0
t1
p1
t2
p1
≠
a a a aatarget
a a b
=
pattern
(c)t3=p1,t4≠ p2,比较2次,next[2]=1
t3
p1
a a a aatarget
a a b
=
pattern
(d)t4=p1,比较1次
t4
p1
t3
t3
p2
t1
p0
t4
p2
t2
p0 p2p0
t4 t4t3 t0
t0 t1 t2t1t0