【算法4】5.3.3.子字符串查找-KMP算法
KMP 是发明此算法的三个人名字首字母。(Knuth, Morris, Pratt)
暴力查找每次匹配失败时都需要回退指针 i,并重新对比已经检查过的字符。
KMP 通过对模式字符串进行预处理,生成一个确定有限状态自动机,
将文本字符串的字符依次放到自动机中,可以直接得到需要和文本字符串下一个字符 text.chatAt(i+1)
匹配的 j 的位置 pattern.chatAt(j)
,
即 j 应该向前移动一个位置(匹配的情况)或将 j 重置到之前的某个位置(不匹配的情况)。
可全屏查看代码
/** * KMP 算法 * */ public class KMP { private static final int R = 256; // 字母表 private int dfa[][]; // 确定有限状态自动机 private int M; /** * 对模式字符串进行预处理,生成确定有限状态自动机 dfa * */ public KMP(String pattern) { // 当匹配失败时,我们可以知道当前匹配的子串是 pattern[i-j, j],接下来需要匹配的子串是从 pattern[i-j+1] 开始 // 所以我们知道接下要放入自动机的字符,而将字符放入自动机又可以得到 j 的新值 // 所以在生成 dfa 的同时也在将模式字符串输入到自动机中,以此更新 X 的值 // dfa 的第一个索引表示的是输入的字符 c,第二个索引表示当前模式字符串的位置 j,值表示下一个状态(即需要将 j 重置到哪个位置) M = pattern.length(); dfa = new int[R][M]; // 初始化自动机的状态,第一个字符匹配成功进入下一个状态,否则保持不动 dfa[pattern.charAt(0)][0] = 1; // 从这里开始一边生成自动机,一边使用自动机 int X = 0; // 记录使用自动机的当前状态 for (int j = 1; j < M; j++) { // 在生成自动机时,从第二个字符开始使用自动机 for (int c = 0; c < R; c++) { dfa[c][j] = dfa[c][X]; // 枚举字符集,并将每个字符放入自动机 } dfa[pattern.charAt(j)][j] = j + 1; // 匹配成功进入下一个状态 X = dfa[pattern.charAt(j)][X]; // 将当前字符放入自动机,更新状态 X } } /** * 在文本中查找模式字符串 * */ public int search(String text) { int N = text.length(); int i, j; for (i = 0, j = 0; i < N && j < M; i++) { j = dfa[text.charAt(i)][j]; } if (j == M) { return i - j; } else { return -1; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现