第03章 串(java版)

33
数数数数 Java 数 )( 3数第3第 3.1 第第第第第第第 3.2 第第第第第第第 3.3 数数数数数数

Transcript of 第03章 串(java版)

Page 1: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

第 3 章 串

3.1 串抽象数据类型 3.2 串的表示和实现 3.3 串的模式匹配

Page 2: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

目的和要求•目的:串作为特殊线性表的实现与应用。•内容:字符串的基本概念,串抽象数据类型,顺序

和链式两种存储结构存储串的特点;采用顺序存储结构实现串的各种操作算法;两种串的模式匹配算法及应用: Brute-Force 算法和 KMP 算法。

•要求:掌握顺序串类的基本操作实现方法,掌握串 的模式匹配算法及应用。

•重点:串数据类型的各种操作实现,两种串的模式 匹配算法及应用。

•难点: KMP 模式匹配算法, next 数组在 KMP算法中 的作用及产生过程。

•实验:顺序串类的基本操作及串的模式匹配算法。

Page 3: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

3.1 串抽象数据类型3.1.1 串的基本概念1. 串定义。 s= " "

2. 子串。 "at"是 "data" 的子串。 3. 串比较。两个串可比较是否相等,也可比较大小。

110 nsss

Page 4: 第03章  串(java版)

《数据结构( 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 串抽象数据类型

Page 5: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

3.2 串的表示和实现

3.2.1 串的存储结构3.2.2 字符串类 String

3.2.3 字符串类 StringBuffer

Page 6: 第03章  串(java版)

《数据结构( 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…

Page 7: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

3.2.2 常量字符串类 String

1. String 类声明 public final class MyString implements

Comparable<MyString>,java.io.Serializ

able

{

private final char[] value;

// 字符数组,私有最终变量,只能赋值一次}

Page 8: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

【例 3.1 】获得整数和实数字符串表示的数值。

整数

数字

实数

数字

- . 数字

E 数字

-e

Page 9: 第03章  串(java版)

《数据结构( 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

Page 10: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

3. 求子串

end-1 endbegin …

a b dc

d e

e gf

buffer

s.value

c

0 length-1… …

h

sub.value

Page 11: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

4. 比较串相等与大小

Page 12: 第03章  串(java版)

《数据结构( 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

Page 13: 第03章  串(java版)

《数据结构( 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

Page 14: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

3.2.3 变量字符串类StringBuffer

public final class MyStringBuffer implements java.io.Serializable

{ private char[] value; // 字符数

组 private int len; // 串长度}

Page 15: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

1. 插入串

Page 16: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

2. 删除子串

Page 17: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

3.3 串的模式匹配

3.3.1 Brute-Force 算法3.3.2 KMP 算法

Page 18: 第03章  串(java版)

《数据结构( 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

Page 19: 第03章  串(java版)

《数据结构( 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

Page 20: 第03章  串(java版)

《数据结构( 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

Page 21: 第03章  串(java版)

《数据结构( 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

Page 22: 第03章  串(java版)

《数据结构( 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

Page 23: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

2. KMP 算法描述( a )( b )

Page 24: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

2. KMP 算法描述( c )

Page 25: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

2. KMP 算法描述( d )

Page 26: 第03章  串(java版)

《数据结构( 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

Page 27: 第03章  串(java版)

《数据结构( 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

Page 28: 第03章  串(java版)

《数据结构( 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

= =

Page 29: 第03章  串(java版)

《数据结构( 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

Page 30: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

图 3-18 KMP 模式匹配过程( a ~b )

Page 31: 第03章  串(java版)

《数据结构( Java 版)(第 3 版)》

图 3-18 KMP 模式匹配过程( c ~e )

Page 32: 第03章  串(java版)

《数据结构( 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

Page 33: 第03章  串(java版)

《数据结构( 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