字符串(String)

来源:互联网 发布:如何删除知乎提问 编辑:程序博客网 时间:2024/05/22 05:29

字符串(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=p0t1=p1……tm1=pm1,则匹配成功,返回模式串pat第0个字符p0在目标串T中匹配的位置。
    (2)如果在其中某个位置i,tipi,比较不等,这时将模式串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++有关字符串的库函数

  • C++提供的有关字符串的函数库的名字为<string.h>,其具体的字符串操作方法说明如下:http://blog.csdn.net/cainv89/article/details/47703949

3.2 STL有关字符串的类库

  • STL提供的有关字符串的类库的名字为<string>,其具体的字符串操作方法说明如下:http://blog.csdn.net/cainv89/article/details/47208019

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,否则函数返回0public:    int operator!()const;                   //判是否串空,若串*this为空,则函数返回1,否则函数返回0public:    AString& operator=(AString& obj);       //串obj赋值给当前串*thispublic:    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,否则函数返回0int AString::operator==(AString& obj)const{    return (strcmp(ch, obj.ch) == 0) ? 1 : 0;}//判是否串不相等,若串*this与obj不相等,则函数返回1,否则函数返回0int AString::operator!=(AString& obj)const{    return (strcmp(ch, obj.ch) != 0) ? 1 : 0;}//判是否串空,若串*this为空,则函数返回1,否则函数返回0int AString::operator!()const{    return (curLength == 0) ? 1 : 0;}//串obj赋值给当前串*thisAString& 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算法,跳转表

1 0
原创粉丝点击