数据结构-串

1.串的定义

是由零个或多个字符组成的有限序列,又名叫字符串。

一般记为s=“a1a2······an”(n>=0) s是串的名称,双引号里面是串的值,注意引号不是串的内容,n称为串的长度。

空串:零个字符的串,长度为0

空格串:只包含空格的串,可以不止一个空格,注意它与空串的区别

子串与主串:串中任意个数的连续字符组成的子序列称为该串的子串,相应的,包含字串的串称为主串

子串在主串的位置就是子串的第一个字符在主串中的序号

2.串的存储结构

串的顺序存储结构

#define MAXLEN 255
typedef struct{
    char ch[MAXLEN+1];//存储串的一维数组
    int length;//串的当前长度长度
}SString;

串的链式存储结构----块链结构

#define CHUNKSIZE 80//块的大小可由用户定义
typedef struct Chunk{
    char ch[CHUNKSIZE];
    struct Chunk*next;
}Chunk;
typedef struct{
    Chunk*head,*tail;//串的头指针和尾指针
    int curlen;//串的当前长度
}LString;//字符串的块链结构

3.朴素的模式匹配算法-BF算法

Index(S,T,pos)

将主串的第pos个字符和模式串的第一个字符比较,

若相等,继续逐个比较后续字符

若不等,从主串的下一个字符起,重新与模式串的第一个字符比较

直到主串的一个连续子串字符序列与模式串相等,返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功。否则匹配失败,返回值0

int Index_BF(SString S,SString T){
    int i=1,j=1;
    while(i<=S.length&&j<=T.length){
        if(s.ch[i]==t.ch[j]){
            ++i;
            ++j;
        }//主串和子串依次匹配下一个字符
        else{
            i=i-j+2;
            j=1;
        }//主串和子串指针回溯重新开始下一次匹配
    }
        if(j>=T.length)
            return i-T.length;//返回匹配的第一个字符下标
        else
            return 0;//模式匹配不成功
}

4.广义表

广义表通常记作:LS=(a1,a2,…an)

其中:LS为表名,n为表的长度,每一个ai为表的元素

习惯上,一般用大写字母表示广义表,小写字母表示原子

表头:若LS非空(n>=1),则其第一个元素a1就是表头

记作head(LS)=a1 注意:表头可以是原子,也可以是子表。

表尾:除表头之外的其它元素组成的表

记作 tail(LS)=(a2,…,an) 注意:表尾不是最后一个元素,而是一个子表。

5.KMP模式匹配算法

//通过计算返回子串T的next数组
void get_next(String T,int *next)
{
    int i;
    int j;
    i=1;
    j=0;
    next[1]=0;
    while(i<T[0]){//T[0]表示串T的长度
        if(j==0||T[i]==T[j]){//T[i]是后缀的单个字符,T[j]是前缀的单个字符
            ++i;
            ++j;
            next[i]=j;//表示下标为i的字符前的字符串最长相等前后缀长度
        }
        else
            j=next[j];//若字符不相同,则j值回溯
    }
}
int Index_KMP(String S,String T,int pos)
{
    //T非空,1<=pos<=StrLength(S)
    int i=pos;//i用于主串S当前位置下标值,若pos不为1,则从pos位置开始匹配
    int j=1;//j用于子串T中当前位置下标值
    int next[255];
    get_next(T,next);
    while(i<=S[0]&&j<=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;
}
next数组值推导

如何推导出一个串的next数组值呢?
在这里插入图片描述
T=“abcdex"

j123456
模式串Tabcdex
next[j]011111

(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",显然”a"与“b"不相等,属于其他情况next[3]=1

(4)以后同理,所以最终此T串的next[j]为011111

这个大家不好理解,就来看看下面我的理解,希望帮助到大家

问题:已知串S= ‘ababaaaba’ , 求其 next 数值序列

前面有k-1个字符一样

(1).next数组第一二位一定分别为0,1

j123456789
模式串ababaaaba
next[j]01

(2)看第三位,按照next数组求解方法。第三位a的前一位是第二位的b,b的next值是1对应内容是a,b与a不同,则继续向前寻找next值对应的内容与第二位的b进行比较。但是找到第一位都没有找到与第二位的b相等的内容,所以第三位a的next值为1,则:

j123456789
模式串ababaaaba
next[j]011

(3)看第四位的b,b的前一位a的next值1对应内容为a,相同,所以该位b的next值就是前一位a的next(第三位的a)值加上1,即为2 (aba)

j123456789
模式串ababaaaba
next[j]0112

(4)看第五位a,a的前一位b的next值2对应内容为b,相等,所以第五位a的next值就是其前一位b的next值加上1,即为3 (abab)

j123456789
模式串ababaaaba
next[j]01123

(5)看第六位a,a的前一位a的next值3对应内容为a,相等,所以该位a的next值就是前一位a的next值加上1,即为4 (ababa)

j123456789
模式串ababaaaba
next[j]011234

(6)看第七位a,a的前一位a的next值4对应内容为b,不相等,向前继续寻找next值对应的内容来与前一位进行比较,b的next值2对应的内容为b,依旧不相等,继续向前寻找,第二位b的next值1对应内容为a,相等。因为是在第二位b处实现的相等,所以第七位a的next值为第二位b的next值上加1,即为2 (ababaa)

j123456789
模式串ababaaaba
next[j]0112342

(7)看第八位b,b的前一位a的next值2对应内容为b,不相等,向前继续寻找next值对应的内容来与前一位进行比较,b的next值1对应的内容为a,相等。因为是在第二位b处实现的相等,所以第八位a的next值为第二位b的next值上加1,即为2 (ababaaa)

j123456789
模式串ababaaaba
next[j]01123422

(8)看第九位,前一位b的next值2对应内容为b,相等,所以此处next值为3 (ababaaab)

j123456789
模式串ababaaaba
next[j]011234223
  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值