《数据结构》(严蔚敏 吴伟民)学习笔记 - 第四章 串

1、串类型的定义

(string)(或字符串)是由零个或多个字符组成的有限序列,一般记为

s = ‘a1a2…an’ (n ≥ 0)

其中,s 是串的名,用单引号括起来的字符序列是串的值;ai(1 ≤ i ≤ n)可以是字母、数字或其它字符;串中字符的数目 n 称为串的长度。零个字符的串称为空串(null string),它的长度为零。

串中任意个连续的字符组成的子序列称为该串的子串。包括子串的串相应地称为主串。通常称子串在序列中的序号为该字符在串中的位置。子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。

称两个串是相等的,当且仅当这两个串的值相等,也就是说,只有当两个串的长度相等,并且各个对应位置的字符都相等。

串值必须用一对单引号括起来,但单引号本身并不属于串,它的作用是为了避免与变量名或数的常量混淆而已。

在各种应用中,空格常常是串的字符集合中的一个元素,因而可以出现在其它字符中间,由一个或多个空格组成的串‘ ’称为空格串(blank string,请注意,此处不是空串)。它的长度为串中空格字符的个数。

对于串的基本操作集可以有不同的定义方法,在使用高级程序设计语言中的串类型时,应以该语言的参考手册为准。

例如,可利用库函数来实现子串的定位,算法如下:

 

 1         String mainString = "Tom Godwin's main string.";
 2         String targetString = "Godwin";        
 3 //        String targetString = "NoString";
 4 
 5         int pos = mainString.indexOf(targetString);
 6         if(pos != -1)
 7         {
 8             System.out.println("Find the target String at: " + pos);            
 9         }
10         else
11         {
12             System.out.println("Not found the target string.");
13         }

 

2、串的表示和实现

1)定长顺序存储表示

 在串的定长顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储去,则可用定长数组。

串连接可以使用 ‘+’ 来实现:

        System.out.println("The concat string is: " + (mainString + targetString));

求子串可以通过 substring 函数实现:

        System.out.println("Ths SubString is: " + mainString.substring(4, 12));

 

2)栈分配存储表示 

这种存储表示的特点是,仍以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配的。

串的比较可以通过 mainString.compareTo(targetString) 来实现,函数返回字符串中第一个字母 ASCII 的差值。

3)串的块链存储表示

由于串结构中的每个数据元素是一个字符,则用链表结构存储串值是,存在一个“节点大小”的问题。即每个节点可以存放一个字符,也可以存放多个字符。为了便于进行串操作,当以链表存储串值时,除头指针外还可以附设一个尾指针表示链表中的最后一个节点,并给出当前串的长度,称如此定义的串存储结构为块链结构。

3、串的模式匹配算法

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

子串的定位操作通常称为串的模式匹配(其中 T 称为模式串)。算法如下:

 

 1     public static int myIndex(String ms, String ts, int pos)
 2     {
 3         int i = pos;
 4         int j = 0;
 5 
 6         while(i < ms.length() && j < ts.length())
 7         {        
 8             if(ms.charAt(i) == ts.charAt(j))
 9             {
10                 i++;
11                 j++;
12             }
13             else
14             {
15                 i = i - j + 1;
16                 j = 0;
17             }
18         }
19 
20         if(j >= ts.length())
21         {
22             return i - ts.length();
23         }
24         else
25         {
26             return -1;
27         }
28     }

 

2)模式匹配的一种改进算法

这种改进算法是 D.E.Knuth 与 V.R.Pratt 和 J.H.Morris 同时发现的,因此称为 KMP 算法。其中的改进在于:每当一趟匹配过程中出现字符比较不等时,不需回溯 i 指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。

依照 KMP 算法,可以得到 next 函数的算法,同时进行了优化:

 

 1     public static void getNext(String ts, int[] nextval)
 2     {
 3         int i = 0;
 4         nextval[0] = -1;
 5         int j = -1;
 6 
 7         while(i < ts.length() - 1)
 8         {
 9             if(j == -1)
10             {
11                 i++;
12                 j++;
13                 if(ts.charAt(i) != ts.charAt(j))
14                     nextval[i] = j;
15                 else
16                     nextval[i] = nextval[j];
17             }
18             else if(ts.charAt(i) == ts.charAt(j))
19             {
20                 i++;
21                 j++;
22                 if(ts.charAt(i) != ts.charAt(j))
23                     nextval[i] = j;
24                 else
25                     nextval[i] = nextval[j];
26             }
27             else
28             {
29                 j = nextval[j];
30             }
31         }
32     }

注:由于使用了字符串变量,对原算法中的标志设置进行了调整:

(1)原算符有效数据从1开始,字符串变量的有效数据从1开始,标志的终止值以及递增的基准值,都进行了相应的调整;

(2)字符串变量的下限为0,所以把判断时的条件拆分,以避免出现异常;

 

KMP 算法如下:

 1     public static int index_KMP(String ms, String ts, int pos, int next[])
 2     {
 3         int loc = -1;
 4         int i = pos -1;
 5         int j = -1;
 6 
 7         while((i <= ms.length() -1) && (j <= ts.length() - 1))
 8         {
 9             if(j == -1)
10             {
11                 i++;
12                 j++;
13             }
14             else if(ms.charAt(i) == ts.charAt(j))
15             {
16                 i++;
17                 j++;
18             }
19             else
20             {
21                 j = next[j];
22             }
23         }
24 
25         if(j >= ts.length())
26         {
27             loc = i - ts.length();
28         }
29 
30         return loc;
31     }

 

End

你可能感兴趣的:(《数据结构》(严蔚敏 吴伟民)学习笔记 - 第四章 串)