DFADeterministic Finite Automaton确定性有限自动机是一种常用的算法模型在Java中广泛应用于敏感词过滤、字符串匹配、词法分析等场景。它的核心特点是每个状态对于同一个输入字符有且只有一个转移状态。基本原理DFA算法通过构建一个状态转移图通常用嵌套Map或数组表示来快速匹配关键词。相比于简单遍历匹配时间复杂度为O(n)n为待匹配文本长度与关键词数量无关。Java实现示例1. 构建DFA节点模型import java.util.*; public class DFAFilter { // 根节点 private MapCharacter, Object rootNode new HashMap(); // 敏感词结束标识 private static final String END_FLAG isEnd; /** * 添加关键词到DFA中 * param keyword 关键词 */ public void addKeyword(String keyword) { if (keyword null || keyword.isEmpty()) return; MapCharacter, Object currentMap rootNode; for (int i 0; i keyword.length(); i) { char c keyword.charAt(i); // 获取下一层节点 MapCharacter, Object nextMap (MapCharacter, Object) currentMap.get(c); if (nextMap null) { nextMap new HashMap(); currentMap.put(c, nextMap); } currentMap nextMap; // 最后一个字符标记结束 if (i keyword.length() - 1) { currentMap.put(END_FLAG, true); } } } /** * 批量添加关键词 */ public void addKeywords(ListString keywords) { for (String keyword : keywords) { addKeyword(keyword); } } }2. 匹配敏感词/** * 检查文本是否包含敏感词并返回第一个匹配的敏感词 */ public String check(String text) { if (text null || text.isEmpty()) return null; for (int i 0; i text.length(); i) { int matchCount 0; MapCharacter, Object currentMap rootNode; char c; for (int j i; j text.length(); j) { c text.charAt(j); currentMap (MapCharacter, Object) currentMap.get(c); if (currentMap null) { break; // 匹配失败重新从下一个字符开始 } matchCount; // 检查是否匹配到完整关键词 if (currentMap.containsKey(END_FLAG)) { return text.substring(i, i matchCount); } } } return null; } /** * 替换文本中的敏感词 * param text 原始文本 * param replaceChar 替换字符 * return 替换后的文本 */ public String replace(String text, char replaceChar) { if (text null || text.isEmpty()) return text; StringBuilder result new StringBuilder(text); Listint[] positions new ArrayList(); for (int i 0; i text.length(); i) { int matchCount 0; MapCharacter, Object currentMap rootNode; char c; for (int j i; j text.length(); j) { c text.charAt(j); currentMap (MapCharacter, Object) currentMap.get(c); if (currentMap null) break; matchCount; if (currentMap.containsKey(END_FLAG)) { positions.add(new int[]{i, i matchCount}); i i matchCount - 1; // 跳过已匹配部分 break; } } } // 执行替换 for (int[] pos : positions) { for (int i pos[0]; i pos[1]; i) { result.setCharAt(i, replaceChar); } } return result.toString(); }3. 完整示例public class DFATest { public static void main(String[] args) { DFAFilter filter new DFAFilter(); // 添加敏感词 filter.addKeywords(Arrays.asList( 色情, 暴力, 赌博, 毒品, 法轮功 )); // 测试文本 String text 这个网站包含色情和暴力内容还有赌博信息。; // 检查敏感词 String sensitive filter.check(text); System.out.println(检测到敏感词: sensitive); // 替换敏感词 String filtered filter.replace(text, *); System.out.println(过滤后: filtered); } } 输出 检测到敏感词: 色情 过滤后: 这个网站包含**和**内容还有**信息。优化版本支持跳过特殊字符/** * 增强版支持忽略特殊字符如空格、标点 */ public class AdvancedDFAFilter { private MapCharacter, Object rootNode new HashMap(); private static final String END_FLAG isEnd; // 忽略字符集合空格、标点符号等 private SetCharacter ignoreChars new HashSet( Arrays.asList( , ,, ., !, ?, ;, :, 、, , 。, , ) ); public void addKeyword(String keyword) { MapCharacter, Object currentMap rootNode; for (char c : keyword.toCharArray()) { currentMap (MapCharacter, Object) currentMap.computeIfAbsent( c, k - new HashMap() ); } currentMap.put(END_FLAG, true); } public String check(String text) { for (int i 0; i text.length(); i) { int matchCount 0; MapCharacter, Object currentMap rootNode; for (int j i; j text.length(); j) { char c text.charAt(j); // 跳过忽略字符 if (ignoreChars.contains(c)) { continue; } currentMap (MapCharacter, Object) currentMap.get(c); if (currentMap null) break; matchCount; if (currentMap.containsKey(END_FLAG)) { return text.substring(i, j 1); } } } return null; } }性能优化建议使用数组代替HashMap当字符集有限如纯英文时可改用MapCharacter, Node或Node[] children数组内存优化使用char[]和int[]手动实现紧凑存储并行处理大文本可分片并行匹配缓存结果对于重复文本缓存匹配结果应用场景✅ 敏感词过滤系统✅ 垃圾邮件检测✅ SQL注入检测✅ 代码语法高亮✅ 正则表达式引擎底层实现DFA算法在Java中实现简单、性能优秀尤其适合需要高性能字符串匹配的场景相比之下比遍历关键词列表快很多。