IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构与算法总结:字符串(KMP模式匹配算法) -> 正文阅读

[数据结构与算法]数据结构与算法总结:字符串(KMP模式匹配算法)

字符串

1. 常用标准串函数

函数名函数功能说明
size_t strlen(char* s)返回s的长度
char* strcpy(char* s1, const char* s2)将字符串s2复制到s1,并返回s1的指针
char* strcat(char* s1, const char* s2)将字符串s2拼接到s1尾部
int strcmp(const char* s1, const char* s2)比较s2和s1,s1大于s2返回正数
char* strchr(char* s, char c)返回s中第一次出现c的位置,如果没有c则返回NULL
char* strrchr(char* s, char c)从s的尾部开始找第一次出现c的位置

String类里面的函数:

在这里插入图片描述

2. 字符串的模式匹配(Pattern matching)

? 所谓模式匹配,是指在文本T(text)中寻找一种特定的模式P(pattren),比如PDF等文档文件中常用的“查找”操作。

? 模式匹配又分 精准匹配近似匹配 两种。

2.1. 朴素的模式匹配算法

? 基本思想是将P从T的开始进行匹配,如果“失配”则向后移动一位。

int NaiveStrMatching(const string T, const string P){
    int i = 0;//P的索引
    int j = 0;//T的索引
    int len_i = P.length();
    int len_j = T.length();
    
    if(len_i >= len_j) return -1;
    while(i<len_i && j<len_j){
        if(T[j]==P[i]){
            j++;i++;
        }
        else{
            j = j-i+1;
            i = 0;
        }
    }
    if(i>=len_i) return j-i+1;
    return -1;
}

? 若设P的长度为M,T的长度为N。该算法最差的时间复杂度为O(M*N).

2.2. KMP模式匹配算法

字符串的特征向量

? 在朴素的模式匹配算法中,存在大量没有必要的回溯。如下图中,在T[3]处发生失配,按照朴素的模式匹配法,会将P一步步移动至完全匹配,且每次匹配都会从头开始匹配。但这并不是必要的,我们完全可以直接将P移动到失配的位置开始匹配。

请添加图片描述

? KMP算法通过定义next数组来计算发生失配时,应从P的哪个位置继续匹配。在KMP算法中,不存在T的回溯。next[i]定义如下为子串P[0:i](不包括P[i])的前缀子串与后缀子串的最大匹配数。且定义next[0] = -1。比如:

Pabaaba
next[i]-101012

? 另一种对next数组更好的理解是,当P[i]与T[j]发生失配时,应使用P[next[i]]来与T[j]进行匹配。(根据next[i]的定义可知,next[i]之前的位置肯定是能匹配上的,不需要再对j进行回溯)。

? 求解next数组的方法如下:

//求next数组
int *findNext(string P){
    int i = 0;
    int k = -1;
    int len = P.length();
    int *next = new int [len];
    next[0] = -1;
    while(i < len-1){	//注意不是i < len.
		while(k != -1 && P[i]!=P[k]){
            k = next[k];
            //这一段看了好久才理解。这其实也是一个KMP的模式匹配,是P的前缀与P的后缀的匹配。
        }
        i++;
        k++;
        next[i]=k;
        //注意next的定义是i之前的最大前缀后缀匹配数,所以i要加一;由于P[i]==P[k],所以要加一
    }
}

? 这种next的定义仍有不好的地方。当碰到连续相同的字母时,时间消耗会增加。比如如下情况:

请添加图片描述
? 这种时候,很明显由于P[2]==P[0],而P[2]失配,所以P[2]必然失配,所以完全可以直接跳到next[2].

? 优化的next数组的求解如下(此时的next的定义不再是前缀后缀匹配数,而是当i处失配时,应和T[i]进行匹配的元素):

//优化的next数组的求算
int* findNext(string P){
    int i = 0;
    int k = -1;
    int len = P.length();
    next[0] = -1;
    while(i<len-1){
        while(k!=-1 && P[i]!=P[k]){
            k = next[k];
        }
        i++;
        k++;
        if(P[i]==P[k]){
            next[i] = next[k];//优化
        }
        else{
            next[i] = k;
        }
    }
}

KMP模式匹配算法

int KMPStrMatching(string T, string P, int* next){
    int i = 0;
    int j = 0;
    int lenp = P.string();
    int lent = T.string();
    if(lent < lenp) return -1;
    while(i < plen && j < tlen){
        if(i==-1 || P[i]==P[j]){
            i++;j++;//i=-1的时候,意味着与j匹配永远是失败的。直接从j+1开始重新匹配。
        }
        else{
            i = next[i];
        
    }
    if(i == plen){
        return j - plen + 1;
    }
    return -1;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:53:24  更:2021-10-16 19:55:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:33:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码