数据结构(考研)第四章 串

第四章 串

4.1 串的定义和实现

4.1.1 串的基本概念

串(字符串):是零个或多个字符组成的有限序列。记作: S=“a1a2a3…”,其中S是串名,ai(1≦i≦n)是单个,可以是字母、数字或其它字符。
串值:双引号括起来的字符序列是串值。
串长:串中所包含的字符个数称为该串的长度。
空串(空的字符串):长度为零的串称为空串,它不包含任何字符。
空格串(空白串):构成串的所有字符都是空格的串称为空白串。
注意:空串和空白串的不同,例如“ ”和“”分别表示长度为1的空白串和长度为0的空串。
子串(substring):串中任意个连续字符组成的子序列称为该串的子串,包含子串的串相应地称为主串。
子串的序号:将子串在主串中首次出现时的该子串的首字符对应在主串中的序号,称为子串在主串中的序号(或位置)。
例如,设有串A和B分别是:
A=“这是字符串”,B=“是”
则B是A的子串,A为主串。B在A中出现了两次,其中首次出现所对应的主串位置是3。因此,称B在A中的序号为3 。
特别地,空串是任意串的子串,任意串是其自身的子串。
串相等:如果两个串的串值相等(相同),称这两个串相等。换言之,只有当两个串的长度相等,且各个对应位置的字符都相同时才相等。
通常在程序中使用的串可分为两种:串变量和串常量。
串常量和整常数、实常数一样,在程序中只能被引用但不能不能改变其值,即只能读不能写。通常串常量是由直接量来表示的,例如语句错误(“溢出”)中“溢出”是直接量。
串变量和其它类型的变量一样,其值是可以改变。

4.1.2 串的存储结构

串是一种特殊的线性表,其存储表示和线性表类似,但又不完全相同。串的存储方式取决于将要对串所进行的操作。串在计算机中有3种表示方式:

  • 定长顺序存储表示:将串定义成字符数组,利用串名可以直接访问串值。用这种表示方式,串的存储空间在编译时确定,其大小不能改变。

    #define MAXLEN 255
    typedef struct {
        char ch[MAXLEN];
        int length;
    }SString;
    
  • 堆分配存储方式:仍然用一组地址连续的存储单元来依次存储串中的字符序列,但串的存储空间是在程序运行时根据串的实际长度动态分配的。

    typedef struct {
        char *ch;
        int length;
    }HString;
    
  • 块链存储方式:是一种链式存储结构表示。

4.2 串的模式匹配

4.2.1 简单的模式匹配算法

子串的定位操作通常称为串的模式匹配,它求的是子串(常称模式串)在主串中的位置。

#include "string"
#include "iostream"
using namespace std;
int Index(string S,string T){
    int i = 1;
    int j = 1;
    while (i <= S.length() && j <= T.length()){
        if (S.substr(i - 1,1) == T.substr(j - 1,1)){
            i++;j++;
        } else{
            i = i-j+2;
            j = 1;
        }
    }
    if (j > T.length()) return i - T.length();
    else return -1;
}

简单匹配算法的最坏时间复杂度为O(nm),其中n为主串长度,m为模式串长度。

4.2.2 串的模式匹配算法–KMP算法

在暴力匹配中,每趟匹配失败都是从模式后移一位再从头开始比较。而某趟已匹配相等的字符序列是模式的某个前缀,这种频繁的重复比较相当于模式串在不断地进行自我比较,这就是低效率的根源。因此,我们可以从分析模式本身的结构着手,如果已匹配相等的前缀序列中有某个后缀正好是模式的前缀,那么就可以将模式滑动到与这些相等字符对齐的位置,主串i指针无须回溯,并从该位置开始继续比较。而模式向后滑动到与这些相等字符对齐的位置,主串i指针无须回溯,并从该位置开始继续比较。

void get_next(string T,int next[]){
    int i = 1,j = 0;
    next[1] = 0;
    while (i<T.length()){
        if (j == 0||T.substr(i - 1,1) == T.substr(j,1)){
            i++;j++;
            next[i] = j;
        } else{
            j = next[j];
        }
    }
}
int Index_KMP(string S,string T,int next[]){
    int i = 1,j = 1;
    while (i<=S.length()&&j<T.length()){
        if (j == 0||T.substr(i - 1,1) == T.substr(j,1)){
            i++;j++;
        } else j = next[j];
    }
    if (j>T.length())return i - T.length();
    else return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bestkasscn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值