串的概念

内容受限(只能是字符)的线性表;串中逻辑关系与线性表相同

零个或多个字符组成的有限序列

(串名)S="(串值)a1,a2,...,an" ((串长)n>=0)

空串用∅表示


  • 子串:一个串中任意个连续字符组成的子序列(含空串)称为该串的子串

  • 真子串:不包含自身的所有子串

  • 主串:包含子串的串

  • 字符位置:字符在序列中的序号为该字符在串中的位置

  • 子串位置:子串第一个字符在主串中的位置

  • 空格串:由一个或多个空格组成的串

  • 串相等:当且仅当两个串的长度相等并且各个对应位置上的字符都相同,这两个串才是相等的

    所有的空串都是相等的


串的抽象数据类型定义

ADT String{

​ 数据对象:D=ai|ai属于Characterset,i=1,2,...,n,n>=0}

​ 数据关系:R1=<ai-1,ai>|ai-1,ai属于D,i=2,3,...,n}

​ 基本操作:

​ StrAssign (&T,chars)

​ StrCompare (S,T)

​ StrLength (S)

​ Concat(&T,S1,S2)

​ SubString(&Sub,S,pos,len)

​ StrCopy(&T,S)

​ StrEmpty(S)

​ ClearString(&S)

​ lndex(S,T,pos)

​ Replace(&S,T,V)

​ Strlnsert(&S,pos,T)

​ StrDelete(&S,pos,len)

​ DestroyStrina(&S)

​ ......

}ADT String


顺序串

顺序串的定义

#define MAXLEN 255

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

串的模式匹配

确定主串中子串第一次出现的位置


算法应用:

  • 搜索引擎
  • 拼写检查
  • 语言翻译
  • 数据压缩

算法种类:

  • BF算法/简单匹配算法(brute-force):暴力破解,采用穷举法

    • 匹配失败

      • 主串:i=i-j+2(回溯)
      • 子串:j=1(重头开始)
    • 匹配成功

      return i-子串长度

    int index_BF1(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;
    }
    
    int index_BF2(SString S,SString T,int pos){
        int i=pos,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;
    }
    

    时间复杂度是O(n*m)

  • KMP算法:速度快

    主串S的指针i不必回溯,可提速到O(n+m)

    image

    例:

    i 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    模式串 a b c a a b b c a b c a a b d a b
    j=next[i] 0 1 1 1 2 2 3 1 1 2 3 4 5 6 7 1 2
    void get_next(SString T,int next[]){
        int i=1,j=0;
        next[1]=0;
        while (j<T.length){
            if(j==0||T.ch[i]==T.ch[j]){
                next[++i]=++j;
            }
            else j=next[j];
        }
    }
    
    int index_KMP(SString S,SString T,int pos,int next[]){
        int i=pos,j=1;
        while(i<S.length&&j<T.length){
            if(j==0||S.ch[i]==S.ch[j]){
                i++;
                j++;
            }
            else j=next[j];
        }
        if(j>T.length) return i-T.length;
        else return 0;
    }
    

    求nextval:

    image

    • 第一位的nextval一定是0

    • 第i位字符与第next[i]位的字符进行比较:

      • 不同:nextval=next值
      • 相同:nextval=第next[i]位的next值
      void get_nextval(SString T,int nextval[]){
        int i=1,j=0;
        int nextval[1]=0;
        while(i<T.length){
          if(j==0||T.ch[i]==T.ch[j]){
            ++i;
            ++j;
            if(T.ch[i]!=T.ch[j]) nextval[i]=j;
            else nextval[i]=nextval[j];
          }
          else j=nextval[j];
        }
      }
      

链串

块链的定义

#define CHUNKSIZE 80    //定义块的大小

typedef struct Chunk{
        char ch[CHUNKSIZE];
    struct Chunk *next;
}Chunk;

typedef struct {
    Chunk *head,*tail;  //串的头指针和尾指针
    int curlen;         //串的当前长度
}LString;               //字符串的块链结构

串的应用

  • 病毒感染监测(字符串的匹配):然后检测某种病毒DNA序列是否在患者的DNA序列中出现过,如果出现过,则此人感染了该病毒,否则没有感染

    例:假设病毒的DNA序列为baa(人的DNA序列是线性;病毒DNA序列是环状,因此病毒DNA:baa,aab,aba)可将病毒的DNA存储两次遍历3(n,n为病毒DNA长度)次

    患者1的DNA序列为aaabbba,则感染

    患者2的DNA序列为babbba,则未感染

posted @ 2023-02-02 15:19  原语  阅读(164)  评论(0编辑  收藏  举报