数据结构---串

来源:互联网 发布:c语言结构 编辑:程序博客网 时间:2024/04/29 06:48

串:
由零个或多个字符构成的有限序列,又叫字符串
一般记为:s=”a1a2a3……an”

子串和主串:
串中任意个数的连续字符组成的子序列称为该串的子串 子串在主串中的位置就是子串的第一个字符在主串中的序号

串的比较:
给定两个串:s=”a1a2a3……an”,t=”b1b2b3……bm”,当满足以下条件之一时,s

串的存储结构:

顺序存储结构:
用一组地址连续的存储单元来存储串中的字符序列。
按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区,一般是用定长数组来定义
数组中也会存储预定义的最大串长度,一般可以将串的长度放在数组0处,或者数组最后,或者规定在串的最后加一个终结符,比如“\0”(表示串的结束)

缺点:
对于一些对字符串的操作(改变字符串长度),比如两串的连接Concat、新串的插入等操作,都有可能使得串序列的长度超过了数组长度MaxSize,会与定长冲突

链式存储结构:
一个结点可以存放一个字符,也可以存放多个字符,最后一个结点若是没有被占满,可以用”#”或其他非串值字符补全

这里写图片描述

链式存储结构在连接串上方便,但是不如顺序存储灵活,性能也不如顺序存储结构

串的操作:
不同的编程语言有不同的串操作,不过大体上是一样的,接触语言时可以看看API

模式匹配算法:

朴素的模式匹配算法:
1) 从主S的第一个字符起和子串T的第一个字符进行比较,若相等,则继续逐个比较主串和子串的后续字符,否则从串主串S的下一个字符起再重新和子串T进行比较。

2) 依此类推,直至子串T中的每个字符依次和主串S的一个连续的字符序列相等,则称模式匹配成功,此时子串T的第一个字符在主串S中的位置就是T在S中的位置,否则模式匹配不成功。

/** * S : 主串 * T : 子串 * pos : 从pso位置后面开始匹配 * 注意:数组的0位置存储数组的长度 */int index(String S, String T, int pos){    int i = pos;  // i是主串字符上的指针    int j = 1;  // j是子串当前位置    while(i <= S[0] && j <= T[0])    {        // 字符匹配成功,匹配下一个字符        if(S[i] == T[j])        {            ++ i;            ++ j;        }        // 字符匹配失败        else        {            i = (i-j+1) + 1;  // 主串指针回到开始匹配位置的下一个位置            j = 1;  // 子串指针回到开始        }    }    // 子串匹配成功    if(j > T[0])        return i - T[0];    // 子串匹配失败    else         return 0;}

KMP模式匹配算法:
i:主串和子串比较时,主串当前位置的下标
主串和子串比较时,不用回溯i指针(不可以变小)

举例:
主串S=”abcababca”,子串T=”abcabx”
第1步:对于开始的比较,前5个字符相等,

第4步:T的首位”a”与T的第四位的”a”相等,后面的”b”也相等。
而在第1步的时候,第四位的”a”和第五位的”b”已经和主串中相应的位置已经比较为相等,所以T的首字符”a”和下一位的”b”就不需要再比较了。

这里写图片描述

在这里,我们只要确定T串中各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度。
注:p1,p2,…,pj-1是T串每个位置上的元素
注意:
第二种情况确定j,可以利用前缀字符和后缀字符相等的字符数n个(j=n+1)
这里写图片描述

这里写图片描述
1. 当j=1时,next[1]=0
2. 当j=2时,j由1到j-1的串是”a”,next[2]=1
3. 当j=3时,j由1到j-1的串是”ab”,next[3]=1
4. 当j=4时,j由1到j-1的串是”aba”,前缀字符”a”与后缀字符”a”相等,所以next[4]=1
5. 当j=5时,j由1到j-1的串是”abab”,前缀字符”ab”与后缀字符”ab”相等,所以next[5]=3
6. 当j=6时,j由1到j-1的串是”ababa”,前缀字符”aba”与后缀字符”aba”相等,所以next[6]=4
7. 当j=7时,j由1到j-1的串是”ababaa”,前缀字符”a”与后缀字符”a”相等,所以next[7]=2
8. 当j=8时,j由1到j-1的串是”ababaaa”,前缀字符”a”与后缀字符”a”相等,所以next[8]=2
9. 当j=9时,j由1到j-1的串是”ababaaab”,前缀字符”ab”与后缀字符”ab”相等,所以next[9]=3

算法实现:

通过计算返回子串T的next数组:

void getNext(String T, int *next){    int i, j;    i = 1;    j = 0;    next[1] = 0;    while(i < T[0])  //  0处存放数组长度    {        if(j == 0 || T[i] == T[j])        {            ++ i;            ++ j;            next[i] = j;        }        else{            j = next[j];        }    }}

返回子串T在主串S中第pos个字符后的位置

int index(String S, String T, int pos){    int i = pos;  // i指示主串S的位置    int j =1;  // j指示子串T的位置    int next[255];  // 定义一个next数组    getNext(T, next);  // 获取T的next数组    while(i <= S[0] && j <= T[0])  // S[0]和T[0]存放数组长度    {        if(j == 0 || S[i] == T[j])  // 两字母相等就继续        {            ++ i;            ++ j;        }        else  // 指针后退重新比较        {            j = next[j];  // j退回合适的位置,i值不变        }    }    if(j > T[0])        return i - T[0];    else         return 0;}
0 0
原创粉丝点击