ACM模板——KMP算法

简介: ACM模板——KMP算法

注释版v1

/*
    时间复杂度:如果文本串的长度为n,模式串的长度为m,那么匹配过程的时间复杂度为O(n),算上计算next的O(m)时间,KMP的整体时间复杂度为O(m + n)。
    算法说明:
            1、先通过目标串(ttr)计算出对应的首尾最长前后缀长度(next[])对应的值
            2、再通过计算出的(next[])“智能”处理目标串在主串中的匹配过程
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
    功能:
        获取 next 数组的值:计算目标串前后缀相同的字符个数
    输入:
         ttr:目标串(下标从0开始)
        next:目标串的最长前缀和最长后缀相同的长度,[标记:长度]=>[-1:0],[0:1],[1:2],[n:n+1]。
              如:"ababaca",长度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分别计算的是 a,ab,aba,abab,ababa,ababac,ababaca 的相同的最长前缀和最长后缀的长度。
              由于 a,ab,aba,abab,ababa,ababac,ababaca 的相同的最长前缀和最长后缀是"","","a","ab","aba","","a",所以next数组的值是[-1,-1,0,1,2,-1,0]
        tlen:目标串长度
*/
void Get_Next(char *ttr,int *next,int tlen)
{
    next[0]=-1; // next[0] 初始化为 -1,-1 表示不存在相同的最大前缀和最大后缀
    for(int i=1,j=-1;i<tlen;i++)
    {
        while(j>-1 && ttr[j+1]!=ttr[i]) // 如果下一个不同,那么 j 就变成 next[j],注意 next[j] 是小于 j 的,无论 j 取任何值
            j=next[j]; // 往前回溯
        if(ttr[j+1]==ttr[i]) // 如果相同,j++
            j++;
        next[i]=j; // 这是把算好的 j 值(就是相同的最大前缀和最大后缀长度)赋给 next[i]
    }
}
/*
    功能:
        在主串中匹配目标串;代码和 Get_Next(...) 很类似
    输入:
         str:主串(下标从0开始)
        slen:主串长度
         ttr:目标串(下标从0开始)
        tlen:目标串长度
    输出:
        若存在,返回第一个字符匹配成功的位置(下标从0开始);否则,返回-1
*/
int Index_KMP(char *str,int slen,char *ttr,int tlen)
{
    int *next=new int[tlen];
    Get_Next(ttr,next,tlen);
    for(int i=0,j=-1;i<slen;i++)
    {
        while(j>-1 && ttr[j+1]!=str[i]) // ttr 和 str 不匹配,且 j>-1:表示 ttr 和 str 有部分匹配
            j=next[j]; // 往前回溯
        if(ttr[j+1]==str[i])
            j++;
        if(j==tlen-1) // 说明 j 移动到 ttr 的最末端,匹配完成(成功)
        {
            return i-tlen+1; // 返回相应的位置(首字符匹配的位置,下标从0开始)
        }
    }
    return -1; // 匹配失败
}
/*
    功能:
        目标串在主串中出现的次数(可重叠);代码和 Get_Next(...) 很类似
    输入:
         str:主串(下标从0开始)
        slen:主串长度
         ttr:目标串(下标从0开始)
        tlen:目标串长度
    输出:
        返回出现(匹配成功)的次数
*/
int Count_KMP(char *str,int slen,char *ttr,int tlen)
{
    int cnt=0;
    int *next=new int[tlen];
    Get_Next(ttr,next,tlen);
    for(int i=0,j=-1;i<slen;i++)
    {
        while(j>-1 && ttr[j+1]!=str[i]) // ttr 和 str 不匹配,且 j>-1:表示 ttr 和 str 有部分匹配
            j=next[j]; // 往前回溯
        if(ttr[j+1]==str[i])
            j++;
        if(j==tlen-1) // 说明 j 移动到 ttr 的最末端,匹配完成(成功)
        {
            //j=-1; // 无须此代码,因为通过 next[] 可处理 j 的值
            //i=i-tlen+1; // 无须此代码(主串往前回溯),因为通过 next[] 可处理这过程
            cnt++;
        }
    }
    return cnt; // 返回匹配成功的次数
}

简化版v1

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void Get_Next(char *ttr,int *next,int tlen)
{
    next[0]=-1;
    for(int i=1,j=-1;i<tlen;i++)
    {
        while(j>-1 && ttr[j+1]!=ttr[i])
            j=next[j];
        if(ttr[j+1]==ttr[i])
            j++;
        next[i]=j;
    }
}
int Index_KMP(char *str,int slen,char *ttr,int tlen)
{
    int *next=new int[tlen];
    Get_Next(ttr,next,tlen);
    for(int i=0,j=-1;i<slen;i++)
    {
        while(j>-1 && ttr[j+1]!=str[i])
            j=next[j];
        if(ttr[j+1]==str[i])
            j++;
        if(j==tlen-1)
            return i-tlen+1;
    }
    return -1;
}
int Count_KMP(char *str,int slen,char *ttr,int tlen)
{
    int cnt=0;
    int *next=new int[tlen];
    Get_Next(ttr,next,tlen);
    for(int i=0,j=-1;i<slen;i++)
    {
        while(j>-1 && ttr[j+1]!=str[i])
            j=next[j];
        if(ttr[j+1]==str[i])
            j++;
        if(j==tlen-1)
            cnt++;
    }
    return cnt;
}

注释版v2

/*
    功能:
        1、【标记 // Index】目标串在主串中首次匹配的索引值
        2、【标记 // Count】目标串在主串中出现的次数(可重叠)
    输入:
         str:主串(下标从0开始)
        slen:主串长度
         ttr:目标串(下标从0开始)
        tlen:目标串长度
    输出:
        1、【标记 // Index】返回首次匹配成功的索引值,否则返回 -1
        2、【标记 // Count】返回出现(匹配成功)的次数
    提示:
        next[i]:
       ----------------------------------------
            i 0 1 2 3 4 5 6 7
        模式串 A B C D A B D '\0'
       next[i] -1 0 0 0 0 1 2 0
*/
int kmp(char *str,int slen,char *ttr,int tlen)
{
//    int rs = 0; // Count
    int *next=new int[tlen+1]; // +1 是因为为了计算最长模式子串时的真前后缀相同长度
    next[0] =  -1;
    for (int i=0,j=-1;i<tlen;i++) // Get_Next
    {
        while (j!=-1 && ttr[i]!=ttr[j])
            j = next[j];
        next[i+1] = ++j;
    }
    for (int i=0,j=0;i<slen;i++) // Index_KMP or Count_KMP
    {
        while (j!=-1 && str[i]!=ttr[j])
            j = next[j];
        if (++j==tlen)
        {
//            rs++; // Count
            return i-j+1; // Index
        }
    }
//    return rs; // Count
    return -1; // Index
}

简化版v2

int kmp(char *str,int slen,char *ttr,int tlen)
{
//    int rs = 0; // Count
    int *next=new int[tlen+1];
    next[0] =  -1;
    for (int i=0,j=-1;i<tlen;i++)
    {
        while (j!=-1 && ttr[i]!=ttr[j])
            j = next[j];
        next[i+1] = ++j;
    }
    for (int i=0,j=0;i<slen;i++)
    {
        while (j!=-1 && str[i]!=ttr[j])
            j = next[j];
        if (++j==tlen)
        {
//            rs++; // Count
            return i-j+1; // Index
        }
    }
//    return rs; // Count
    return -1; // Index
}
目录
相关文章
|
6月前
|
存储 机器学习/深度学习 算法
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty  敏感词
|
5月前
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
165 0
|
8月前
|
算法 安全 搜索推荐
套用算法模板备案审核问题增多的原因及解决建议
随着算法备案要求的完善,企业常因使用网上廉价模板而遭遇审核通过率低、问题增多的困境。本文分析了审核不通过的原因,包括模板缺乏针对性、审核标准严格、审核人员主观差异及企业准备不足等,并提出建议:深入了解备案要求、准备详尽材料、避免通用模板、寻求专业帮助。备案后还需持续合规管理,确保算法服务安全运行。
|
算法 C++
A : DS串应用–KMP算法
这篇文章提供了KMP算法的C++实现,包括计算模式串的next数组和在主串中查找模式串位置的函数,用于演示KMP算法的基本应用。
|
算法
第四章 KMP算法理论基础
第四章 KMP算法理论基础
239 0
|
算法
KMP算法
KMP算法
147 0
|
算法
KMP算法
KMP算法
114 0
|
28天前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
168 0
|
1月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
130 2
|
2月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
187 3

热门文章

最新文章