字符串(String)

字符串(String)

1. 字符串的概念

1.1 字符串的定义
  • 字符串,是一串文字和符号的序列,是由零个或多个字符的顺序排列所组成的数据结构,其基本组成元素是单个字符(char),字符串的长度可变。
  • 字符串简称为串(String),是n(n≥0)个字符的一个有限序列。通常可记为S=” a0a1a2an1 ”,其中,S是串名,可以是串变量名,也可以是串常量名。
  • 用引号‘…’或“…”作为分界符括起来的叫做串值,其内的 ai 是串中的字符(0 ≤ i< n),n是串中的字符个数,也叫作串的长度,它不包括作为分界符的引号,也不包括串结束符‘\0’。
1.2 字符串的存储表示
  • 字符串是一种特殊的线性结构,其存储表示有两种:数组存储表示和链接存储表示。
  • 顺序串:字符串的数组存储表示简称为顺序串。
    (1)它用一组地址连续的存储单元来存储字符串中的字符序列。
    (2)可以使用定长的字符数组来实现。
    (3)如果使用C语言中的类型定义,顺序串的存储分配可以分为两种:静态分配的数组表示和动态分配的数组表示。
  • 链串:串的块链存储的组织形式与一般的单链表类似,主要区别在于,串中的一个存储结点可以存储多个字符。
    (1)通常将链串中每个存储结点所存储的字符个数成为结点大小。
    (2)当结点大小大于1时,串的最后一个结点的各个数据域不一定总能全部被字符占满,此时,应在这些未占用的数据域里不上不属于字符集的特殊字符(如“#”)以示区别。
    (3)结点大小为1时存储密度低但操作方便,而结点大小大于1时存储密度高但操作不方便,具体如下图所示:
1.3 空串和空白串的区别
  • 空串:长度为零的串叫做空串,除串结束符外,它不包含任何其他字符。
  • 空白串:空白串的长度不为零,除串结束符外,它包含的其他字符均为空格。

2. 字符串的模式匹配

  • 模式匹配(Pattern matching):查找模式串在目标串中的匹配位置的运算。
  • 字符串的模式匹配问题描述:设有两个字符串T和pat,若打算在串T中查找是否有与串pat相等的子串,则称串T为目标(Target),称串pat为模式(Pattern)。
2.1 朴素的模式匹配——B-F算法(由Brute和Force提出,一种带回溯的字符串匹配算法)
  • 基本想法:用串pat的字符依次与串T中的字符做比较。
  • 算法原理如下:
    (1)如果 t0 = p0 t1 = p1 …… tm1 = pm1 ,则匹配成功,返回模式串pat第0个字符 p0 在目标串T中匹配的位置。
    (2)如果在其中某个位置i, ti pi ,比较不等,这时将模式串pat右移一位,用pat中字符从头开始与T中字符依次比较,如此反复执行,直到得出结果:结果一,执行到某一趟,模式串的所有字符都与目标串对应字符相等,则匹配成功,结束算法;结果二,pat已经移到最后可能与T比较的位置,但不是每一个字符都能与T匹配,则匹配失败,结束算法。
2.2 模式匹配的改进算法——KMP算法(由D.E.Knuth、J.H.Morris和V.R.Pratt提出,一种无回溯的字符串匹配算法,更高效)
  • 基本想法:引入一个跳转表next[],跳过不必要的比较过程,避免回溯,提高效率。
  • 算法原理如下:
    (1)用一个next特征函数来确定,当模式P中第j个字符与目标S中相应字符失配时,模式P中应当由哪个字符(设为第k+1个)与目标中刚失配的字符重新继续进行比较。
    (2)设模式P= p0p1pj2pj1 ,则它的next特征函数定义如下:
    这里写图片描述

3. 字符串相关库函数

3.1 C++有关字符串的库函数

3.2 STL有关字符串的类库

4. 字符串的实现

4.1 字符串的自定义类
  • 文件:AString.h

    
    #ifndef ASTRING_H_
    
    
    #define ASTRING_H_
    
    
    
    #include <iostream>
    
    
    #include <string.h>
    
    //#include <strstream>
    
    using namespace std;
    
    const int defaultSize = 128;
    
    class AString
    {
    public:
        AString(int sz = defaultSize);  //构造函数,构造一个最大长度为sz,实际长度为0的字符串
        AString(const char *init);      //构造函数,构造一个最大长度为maxSize,由init初始化的新字符串对象
        AString(const AString& obj);    //拷贝构造函数,由一个已有的字符串对象ogj构造一个新字符串
        ~AString();                        //析构函数,释放动态分配的串空间并撤销改字符串对象
    
    public:
        int  Length()const;                     //函数返回串*this的实际长度
    
    public:
        AString operator()(int pos, int len);   //当0<=pos<maxSize且0<=len且pos+len<maxSize时,则在串*this中从pos所指出位置开始连续取len个字符组成子串返回
    
    public:
        int operator==(AString& obj)const;      //判是否串相等,若串*this与obj相等,则函数返回1,否则函数返回0
        int operator!=(AString& obj)const;      //判是否串不相等,若串*this与obj不相等,则函数返回1,否则函数返回0
    
    public:
        int operator!()const;                   //判是否串空,若串*this为空,则函数返回1,否则函数返回0
    
    public:
        AString& operator=(AString& obj);       //串obj赋值给当前串*this
    
    public:
        AString& operator+=(AString& obj);      //若length(*this)+length(obj)<maxSize,则把串obj接在串*this后面
    
    public:
        char& operator[](int i);                //取*this的第i个字符
    
    public:
        //若串pat与串*this中的某个子串匹配,则函数返回第1次匹配时子串在串*this中的位置,若串pat为空或在串*this中没有匹配子串,则函数返回-1
        int Find(AString* pat)const;                        //B-F算法,朴素的模式匹配,带回溯的字符串匹配算法
        int fastFind(AString* pat, int next[])const;        //KMP算法,模式匹配的改进算法,无回溯的字符串匹配算法
    
    public:
        void getNext(int next[]);               //计算next[]的算法
    
    private:
        char *ch;       //串存放数组
        int curLength;  //串的实际长度
        int maxSize;    //存放数组的最大长度
    };
    
    
    #endif /*ASTRING_H_*/
    
4.2 字符串操作的实现
  • 文件:AString.cpp

    
    #include "AString.h"
    
    
    //构造函数,构造一个最大长度为sz,实际长度为0的字符串
    AString::AString(int sz)
    {
        if (sz >= 0)
        {
            maxSize = sz;
            curLength = 0;
            ch = new char[maxSize + 1];
            ch[0] = '\0';
        }
    }
    
    //构造函数,构造一个最大长度为maxSize,由data初始化的新字符串对象
    AString::AString(const char *init)
    {
        int len = strlen(init);
        maxSize = (len > defaultSize) ? len : defaultSize;
        curLength = len;
        ch = new char[maxSize + 1];
        strcpy(ch, init);
    }
    
    //拷贝构造函数,由一个已有的字符串对象ogj构造一个新字符串
    AString::AString(const AString& obj)
    {
        maxSize = obj.maxSize;
        curLength = obj.curLength;
        ch = new char[maxSize + 1];
        strcpy(ch, obj.ch);
    }
    
    //析构函数,释放动态分配的串空间并撤销改字符串对象
    AString::~AString()
    {
        delete[] ch;
        ch = NULL;
    }
    
    //函数返回串*this的实际长度
    int  AString::Length()const
    {
        return curLength;
    }
    
    //当0<=pos<maxSize且0<=len且pos+len<maxSize时,则在串*this中从pos所指出位置开始连续取len个字符组成子串返回
    AString AString::operator()(int pos, int len)
    {
        AString temp;
        if ((pos >= 0) && (pos < maxSize) && (len >= 0) && ((pos + len) < maxSize))
        {
            len = ((pos + len - 1) >= curLength) ? (curLength - pos) : len;
            temp.curLength = len;
            for (int i = 0, j = pos;i < len;i++, j++)
            {
                temp.ch[i] = ch[j];
            }
            temp.ch[len] = '\0';
        }
        return temp;
    }
    
    //判是否串相等,若串*this与obj相等,则函数返回1,否则函数返回0
    int AString::operator==(AString& obj)const
    {
        return (strcmp(ch, obj.ch) == 0) ? 1 : 0;
    }
    
    //判是否串不相等,若串*this与obj不相等,则函数返回1,否则函数返回0
    int AString::operator!=(AString& obj)const
    {
        return (strcmp(ch, obj.ch) != 0) ? 1 : 0;
    }
    
    //判是否串空,若串*this为空,则函数返回1,否则函数返回0
    int AString::operator!()const
    {
        return (curLength == 0) ? 1 : 0;
    }
    
    //串obj赋值给当前串*this
    AString& AString::operator=(AString& obj)
    {
        //两个串相等为自我赋值,否则字符串自身赋值出错
        if (&obj != this)
        {
            delete[] ch;
            maxSize = obj.maxSize;
            curLength = obj.curLength;
            ch = new char[maxSize + 1];
            strcpy(ch, obj.ch);
        }
        return *this;
    }
    
    //若length(*this)+length(obj)<maxSize,则把串obj接在串*this后面
    AString& AString::operator+=(AString& obj)
    {
        char *temp = ch;
        curLength += obj.curLength;
        maxSize = (maxSize >= curLength) ? maxSize : curLength;
        delete[] ch;
        ch = new char[maxSize+1];
        strcpy(ch, temp);
        strcat(ch, obj.ch);
        delete[] temp;
        return *this;
    
    }
    
    //取*this的第i个字符
    char& AString::operator[](int i)
    {
        if ((i < 0) || (i >= curLength))
        {
            exit(1);
        }
        return ch[i];
    }
    
    //若串pat与串*this中的某个子串匹配,则函数返回第1次匹配时子串在串*this中的位置,若串pat为空或在串*this中没有匹配子串,则函数返回-1
    //B-F算法,朴素的模式匹配,带回溯的字符串匹配算法
    int AString::Find(AString* pat)const
    {
        int i = 0;
        int j = 0;
        for (i = 0;i <= curLength - pat->curLength;i++)
        {
            for (j = 0;j < pat->curLength;j++)
            {
                if (ch[i + j] != pat->ch[j])
                {
                    break;
                }
            }
            if (j == pat->curLength)
            {
                return i;
            }
        }
        return -1;
    }
    
    //KMP算法,模式匹配的改进算法,无回溯的字符串匹配算法
    int AString::fastFind(AString* pat, int next[])const
    {
        int posP = 0;                   //模式串的扫描指针
        int posT = 0;                   //目标串的扫描指针
        int lengthP = pat->curLength;   //模式串的长度
        int lengthT = curLength;        //目标串的长度
        while ((posP < lengthP) && (posT < lengthT))    //对两串扫描
        {
            if ((posP == -1) || (pat->ch[posP] == ch[posT]))    //对应字符匹配
            {
                posP++;
                posT++;
            }
            else
            {
                posP = next[posP];
            }
        }
        if (posP < lengthP)
        {
            return -1;
        }
        else
        {
            return posT - lengthP;
        }
        return -1;
    }
    
    //计算next[]的算法
    void AString::getNext(int next[])
    {
        int j = 0;
        int k = -1;
        next[0] = -1;
        while (j < curLength) 
        {
            if ((k == -1) || (ch[j] == ch[k]))
            {
                j++;
                k++;
                next[j] = k;
            }
            else
            {
                k = next[k];
            }
        }
    }

参考文献:
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第四章
[2] 百度搜索关键字:字符串,KMP算法,跳转表

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值