作者: YanyZhao | 来源:发表于2020-03-24 22:55 被阅读0次

串string:字符组成的有限序列。
一组地址连续的储存单元,储存字符序,可在执行过程中动态分配,如堆。
s = "a1a2...an": 相邻的字符有前驱和后继关系。

  • 空格串:" "
  • 子串:
  • 主串:

大小比较:对组成串的字符串的编码进行比较(ASCII)。

  • ASCII: 7位二进制(128)——> 8位二进制(256)
  • Unicode: 16位二进制(前256位与ASCII一样)

串的主要功能: 查找子串位置、得到指定子串、替换指定子串等。
链式储存:数据域存一个字符浪费(可存多个字符——根据需要),但不如顺序结构好用。

朴素的模式匹配算法

朴素的模式匹配算

主串长度为n,子串长度为m,则时间复杂度最坏式 O((n-m+1)m)~ O(nm)

KMP模式匹配算法

  • 优点:不用将主串中已经匹配过的字符进行回溯——主串的下标i值不可以变小,仅变化模式串的下标j
  • 时间复杂度O(n+m)
next[ j ] ☆下标从1开始,根据模式串计算得 next[ j ]

j下标从1开始: next[j]数组:代表j指针之前,字符串的真前缀和真后缀的最大匹配长度k + 1
j下标从0开始: next[j]数组:代表j指针之前,字符串的真前缀和真后缀的最大匹配长度k

  • next[j] = k;:当模式串的第j位与主串的第i位失配时,这时主串的位置不回溯,将模式串退到第k位,再次与主串的第i位进行匹配。直到匹配成功或超出字符数量为止。

代码层面理解: j下标从0开始

参考文章:(原创)详解KMP算法,

  • 该文章中T为主串,P为模式串。本人代码部分p为主串,t为模式串。

思想:利用已经部分匹配这个有效信息,保持i指针不回溯,通过修改j指针,让模式串尽量地移动到有效位置。
★: next[j]的值(也就是k)表示,当T[j] != P[i]时,j指针的下一步移动位置。

当匹配失败时,j要移动到下一个位置k。存在这样的性质:最前面的k个字符(真前缀)和j之前的最后k个字符(真后缀)是一样的,即模式串P[0~k-1] == P[j-k ~ j-1]

void get_next(int next[], string t)
{
    int j = 0, k = -1;
    next[0] = -1; //步骤1
    while (j < t.size() - 1)
    {
        if (k == -1 || t[j] == t[k])
        {
            next[++j] = ++k; //步骤2
        }
        else
            k = next[k]; //步骤3
    }
}

步骤1:next[0]=-1

j=0位,不匹配

步骤2:P[k] == P[j],有next[j+1] = next[j]+1 = k+1

P[k] == P[j]

步骤2改进

P[j] == P[next[j]]

步骤3:P[k] != P[j],k=next[k];

P[k] != P[j],k回溯到next[k]
//kmp算法
int kmp(string p, string t)
{
    int i = 0;//主串位置
    int j = 0;//模式串位置
    int *next = new int[t.size()];
    get_next(next, t);
    while ( i < p.size() && j < t.size() ) {
        if (j == -1 || p[i] == t[j]) //主串p[i]与模式串t[j]位比较,若相等,同时往后移一位。
        {
            ++i; ++j;
        }
        else
                      //i=i-j+1; // i无需回溯
            j = next[j]; //j回溯到指定位置,
    }
    delete[] next;
    if (j == t.size()) //匹配成功
        return (i - j);
    else
        return -1;
}

相关文章

  • 串手串

    某多买的手工材料到了,晚饭后回到家,开始串手串。 之前在老家在店里买的石榴石手串200多,有点紧,勒胳膊。 想着买...

  • 糖葫芦

    糖葫芦啊,糖葫芦, 串一串啊,串一串, 五个串一串, 味道酸又甜。

  • 日日行

    一串串的星月隐了,一串串的太阳升起来;一串串的日子里,和着一串串的柴米油盐;一串串的笑声后,或躲着一串串...

  • 模式匹配中Brute-Force与KMP算法关键提取

    模式匹配是串结构的一种操作方法,用于串的匹配。待匹配串称为主串(也叫目标串),执行串称为子串(也叫模式串)。模式匹...

  • iOS中的NSString与NSMutableString

    字符串的创建 字符串读写 字符串的比较 字符串的搜索 字符串截取 字符串替换 字符串与路径 字符串转换 NSMut...

  • Javascript知识点整合

    字符串 单行字符串: ‘字符串’或“字符串” 多行字符串: `多行字符串` 字符串操作: 字符串连接‘+’号 长度...

  • DS串应用--串替换

    题目描述 给出主串、模式串、替换串,用KMP算法找出模式串在主串的位置,然后用替换串的字符替换掉模式串 本题只考虑...

  • Go 关于串的三个经典案例

    子串查找 介绍 子串查找,也可以成为字符串查找。其中有两个字符串,分为主串和子串(模式串)。在主串中查找是否含有子...

  • php 字符串常见方法汇总

    字符串拼接 字符串检索 字符串截取 字符串替换 字符串大小写转化 字符串转数组 字符串格式化

  • jq的字符串操作

    字符串拼接 字符串长度 子串 split trim 子串替换

网友评论

      本文标题:

      本文链接:https://www.haomeiwen.com/subject/vngoyhtx.html