KMP算法
应用于字符串匹配,主要思想就是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,利用这些信息避免从头再做匹配。
如何利用已经匹配的文本内容?前缀表
前缀表:用来回退,记录模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。
前缀:不包含最后一个字符的所有以第一个字符开始的连续子串
后缀:不包含第一个字符的所有以最后一个字符结尾的连续子串
example:
文本串: a a b a a b a a f a
模式串: a a b a a f
匹配的过程中文本串b和模式串f 不匹配,而模式串f之前的部分字符串(aabaa)的最长相等的前缀和后缀字符串是字符串aa,因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串后面,我们可以找到与其相同的前缀的后面重新匹配即可,这样避免匹配失败就从头匹配的复杂度过高问题,利用了已经匹配的信息。
如何计算前缀表
example: a a b a a f
对于前1个字符的子串a, 最长相同前后缀长度为0
对于前2个字符的子串a a, 最长相同前后缀长度为1
对于前3个字符的子串a a b, 最长相同前后缀长度为0
对于前4个字符的子串a a b a, 最长相同前后缀长度为1
对于前5个字符的子串a a b a a , 最长相同前后缀长度为2
对于前6个字符的子串a a b a a f, 最长相同前后缀长度为0
前缀表和模式串联系在一起,具体如图
前缀表与next数组:next数组可以是前缀表,也可以是前缀表统一减一
时间复杂度分析:设文本串长度为n, 模式串长度为m,匹配的过程中不断根据前缀表调整匹配的位置,可以看出匹配的过程是O(n)(因为前缀表使得文本串中不需要回退位置,只需要每次从匹配错误的位置重新匹配,因此是O(n),位置调整是基于模式串调整的),单独生成next数组需要时间复杂度O(m),整个KMP算法的时间复杂度是O(n+m)的。
构造next数组:计算模式串的前缀表:
统一减一的前缀表:与索引相匹配 void getNext(int* next, const string& s){ int j = -1; next[0] = j; for(int i = 1;i < s.size();i++){ while(j>=0 && s[i]!=s[j+1]){ j = next[j]; } if(s[i]==s[j+1]){ j++; } next[i]=j; } };
与前缀长度相匹配:
void getNext(int* next, const string& s){ int j = 0; next[0] = j; for(int i = 1;i<s.size();i++){ while( j > 0 && s[i] != s[j]){ j = next[j-1]; } if(s[i] == s[j]){ j++; } next[i] = j; } };
class Solution{ public: void getNext(int* next, const string& s){ int j = -1; next[0] = j; for(int i = 1; i < s.size();i++){ while(j >= 0 && s[i] != s[j+1]){ j = next[j]; } if(s[i] == s[j+1]){ j ++; } next[i] = j; } } int strStr(string haystack, string needle){ if(needle.size()>haystack.size()|| needle.size()==0){ return -1; } int next[needle.size()]; getNext(next, needle); int j = -1; for(int i = 0;i<haystack.size();i++){ while(j>=0 && needle[j+1]!=haystack[i]){ j = next[j]; } if(haystack[i] == next[j+1]){ j++; } if(j == needle.size()-1){ return(i-needle.size()+1); } } return -1; } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)