java关键词组匹配算法

首先我们将对代码进行基础构思:

一、 创建TrieNode 类

Trie 树的节点类,用于构建 Trie 树。TrieNode 类有以下成员变量:
children:一个 Map,用于存储当前节点的子节点,key 是字符,value 是对应的子节点 TrieNode。
isEndOfWord:布尔值,表示当前节点是否是一个关键词的结尾。
fail:失败指针,指向其他节点,用于构建 Trie 树的失败指针。
matchedKeywords:一个 Set,用于存储匹配到的关键词。

/*** Trie树节点类*/
class TrieNode {Map<Character, TrieNode> children; // 子节点映射表boolean isEndOfWord; // 是否是关键词结尾TrieNode fail; // 失败指针,指向其他节点Set<String> matchedKeywords; // 匹配到的关键词集合public TrieNode() {children = new HashMap<>();isEndOfWord = false;fail = null;matchedKeywords = new HashSet<>();}
}

二 、创建Trie 类

Trie 类用于构建 Trie 树,并实现相关功能。Trie 类有以下成员变量:
root:Trie 树的根节点。
Trie 类有以下成员方法:
insert(String word): 将一个关键词插入到 Trie 树中。在插入过程中,逐个字符遍历,如果当前字符不存在对应的子节点,则创建一个新的节点并插入;如果当前字符已存在对应的子节点,则直接获取子节点继续遍历。最后标记当前节点为关键词结尾,并将该关键词添加到节点的 matchedKeywords 集合中。
buildFailPointers():构建 Trie 树的失败指针。通过 BFS 遍历 Trie 树,为每个节点设置失败指针,使得在搜索过程中可以快速回溯失败节点,从而实现 KMP 算法的功能。同时,也将匹配到的关键词集合合并到当前节点的 matchedKeywords 中。
search(String text):在文本中搜索关键词。根据 Trie 树,逐个字符遍历文本,并根据失败指针快速回溯,找到匹配的关键词。

/*** Trie树类*/
class Trie {private TrieNode root;public Trie() {root = new TrieNode();}/*** 插入关键词到Trie树* @param word*/public void insert(String word) {TrieNode current = root;for (char ch : word.toCharArray()) {current.children.putIfAbsent(ch, new TrieNode());current = current.children.get(ch);}current.isEndOfWord = true;current.matchedKeywords.add(word);}/*** 构建Trie树的失败指针,用于KMP算法*/public void buildFailPointers() {Queue<TrieNode> queue = new LinkedList<>();for (TrieNode child : root.children.values()) {child.fail = root;queue.add(child);}while (!queue.isEmpty()) {TrieNode current = queue.poll();for (Map.Entry<Character, TrieNode> entry : current.children.entrySet()) {char ch = entry.getKey();TrieNode child = entry.getValue();TrieNode failNode = current.fail;while (failNode != null && !failNode.children.containsKey(ch)) {failNode = failNode.fail;}if (failNode == null) {child.fail = root;} else {child.fail = failNode.children.get(ch);child.matchedKeywords.addAll(child.fail.matchedKeywords); // 合并匹配关键词集合}queue.add(child);}}}

三. 创建ChineseKeywordMatcher 类

ChineseKeywordMatcher 类是程序的入口点,负责读取用户输入的文本,并进行匹配。
ChineseKeywordMatcher 类有以下成员方法:
在主方法main中,我们定义了多组关键词,构建 Trie 树并插入关键词,然后构建失败指针,接着获取用户输入的文本,最后通过并行计算搜索组合关键词,并输出匹配的结果。
searchCombinationsParallel(String text, List<List> keywordGroups):并行计算搜索组合关键词,并返回匹配的组合关键词集合。在这个方法中,我们使用线程池来同时搜索多组关键词,从而提高搜索效率。
generateCombinations(String text, List keywords, StringBuilder currentCombination, Set matchedKeywords):生成所有组合关键词,并在文本中查找匹配。这是一个辅助方法,在主方法中调用,并通过非递归方式生成组合关键词,然后根据 Trie 树在文本中查找匹配。

    public static void main(String[] args) throws InterruptedException, ExecutionException {// 定义多组关键词List<List<String>> keywordGroups = new ArrayList<>();keywordGroups.add(Arrays.asList("人工智能", "AI"));keywordGroups.add(Arrays.asList("隐私计算", "联邦学习", "可信执行环境"));// 创建Trie树并插入关键词Trie trie = new Trie();for (List<String> keywords : keywordGroups) {for (String keyword : keywords) {trie.insert(keyword);}}// 构建Trie树的失败指针,用于KMP算法trie.buildFailPointers();// 获取用户输入的文本Scanner scanner = new Scanner(System.in);System.out.print("请输入中文文本:");String userInput = scanner.nextLine();scanner.close();// 并行计算搜索组合关键词,并返回匹配的组合关键词集合Set<String> matchedCombinationKeywords = searchCombinationsParallel(userInput, keywordGroups);if (!matchedCombinationKeywords.isEmpty()) {System.out.println("匹配的组合关键词:");for (String keyword : matchedCombinationKeywords) {System.out.println(keyword);}} else {System.out.println("没有匹配到组合关键词。");}}

四、 输入文本

在代码的 main 方法中,通过 Scanner 读取用户输入的中文文本。

  // 获取用户输入的文本Scanner scanner = new Scanner(System.in);System.out.print("请输入中文文本:");String userInput = scanner.nextLine();scanner.close();

注意:这里有部分长字符串需要剔除空格才可以精准匹配

五、 匹配组合关键词

在 searchCombinationsParallel 方法中,我们使用线程池和并行计算来搜索多组关键词的组合关键词。在 generateCombinations 方法中,我们通过非递归方式生成组合关键词,并利用 Trie 树在文本中查找匹配。最终输出匹配到的组合关键词。

  /*** 并行计算:在文本中搜索组合关键词,并返回匹配的组合关键词集合* @param text* @param keywordGroups* @return* @throws InterruptedException* @throws ExecutionException*/public static Set<String> searchCombinationsParallel(String text, List<List<String>> keywordGroups) throws InterruptedException, ExecutionException {// 获取可用处理器核心数,并创建对应数量的线程池int numThreads = Runtime.getRuntime().availableProcessors();ExecutorService executorService = Executors.newFixedThreadPool(numThreads);// 使用线程安全的集合来保存匹配结果Set<String> matchedCombinationKeywords = new ConcurrentSkipListSet<>();// 创建并行任务列表List<Callable<Set<String>>> tasks = new ArrayList<>();for (List<String> keywords : keywordGroups) {tasks.add(() -> {Set<String> matchedKeywords = new HashSet<>();generateCombinations(text, keywords, new StringBuilder(), matchedKeywords);return matchedKeywords;});}// 并行执行任务,获取结果并合并到结果集合List<Future<Set<String>>> futures = executorService.invokeAll(tasks);for (Future<Set<String>> future : futures) {matchedCombinationKeywords.addAll(future.get());}// 关闭线程池executorService.shutdown();return matchedCombinationKeywords;}/*** 生成所有组合关键词,并在文本中查找匹配* @param text* @param keywords* @param currentCombination* @param matchedKeywords*/private static void generateCombinations(String text, List<String> keywords, StringBuilder currentCombination, Set<String> matchedKeywords) {int[] indices = new int[keywords.size()]; // 记录每组关键词的索引while (true) {StringBuilder currentCombinationKeyword = new StringBuilder();// 生成当前的组合关键词for (int i = 0; i < keywords.size(); i++) {String keyword = keywords.get(i);// int index = indices[i];if (currentCombinationKeyword.length() > 0) {currentCombinationKeyword.append(",");}currentCombinationKeyword.append(keyword);indices[i]++;}Trie trie = new Trie();for (String keyword : currentCombinationKeyword.toString().split(",")) {trie.insert(keyword);}trie.buildFailPointers();Set<String> matched = trie.search(text);if (!matched.isEmpty()) {matchedKeywords.addAll(matched);}// 移动索引,类似组合数学中的组合生成算法int j = keywords.size() - 1;while (j >= 0 && indices[j] == keywords.size()) {indices[j] = 0;j--;}if (j < 0) {break;}}}

根据以上步骤思路我们编写完整代码,具体完整代码如下所示:

package cn.konne.konneim.download;
import java.util.*;
import java.util.concurrent.*;/*** Trie树节点类*/
class TrieNode {Map<Character, TrieNode> children; // 子节点映射表boolean isEndOfWord; // 是否是关键词结尾TrieNode fail; // 失败指针,指向其他节点Set<String> matchedKeywords; // 匹配到的关键词集合public TrieNode() {children = new HashMap<>();isEndOfWord = false;fail = null;matchedKeywords = new HashSet<>();}
}/*** Trie树类*/
class Trie {private TrieNode root;public Trie() {root = new TrieNode();}/*** 插入关键词到Trie树* @param word*/public void insert(String word) {TrieNode current = root;for (char ch : word.toCharArray()) {current.children.putIfAbsent(ch, new TrieNode());current = current.children.get(ch);}current.isEndOfWord = true;current.matchedKeywords.add(word);}/*** 构建Trie树的失败指针,用于KMP算法*/public void buildFailPointers() {Queue<TrieNode> queue = new LinkedList<>();for (TrieNode child : root.children.values()) {child.fail = root;queue.add(child);}while (!queue.isEmpty()) {TrieNode current = queue.poll();for (Map.Entry<Character, TrieNode> entry : current.children.entrySet()) {char ch = entry.getKey();TrieNode child = entry.getValue();TrieNode failNode = current.fail;while (failNode != null && !failNode.children.containsKey(ch)) {failNode = failNode.fail;}if (failNode == null) {child.fail = root;} else {child.fail = failNode.children.get(ch);child.matchedKeywords.addAll(child.fail.matchedKeywords); // 合并匹配关键词集合}queue.add(child);}}}/*** 在文本中搜索关键词,并返回匹配的关键词集合* @param text 要匹配得文本串* @return*/public Set<String> search(String text) {TrieNode current = root;Set<String> matchedKeywords = new HashSet<>();StringBuilder matchedKeyword = new StringBuilder();for (char ch : text.toCharArray()) {while (current != root && !current.children.containsKey(ch)) {current = current.fail;}if (current.children.containsKey(ch)) {current = current.children.get(ch);matchedKeyword.append(ch);if (current.isEndOfWord) {matchedKeywords.addAll(current.matchedKeywords);}} else {current = root;matchedKeyword.setLength(0);}}return matchedKeywords;}
}public class ChineseKeywordMatcher {public static void main(String[] args) throws InterruptedException, ExecutionException {// 定义多组关键词List<List<String>> keywordGroups = new ArrayList<>();keywordGroups.add(Arrays.asList("人工智能", "AI"));keywordGroups.add(Arrays.asList("隐私计算", "联邦学习", "可信执行环境"));// 创建Trie树并插入关键词Trie trie = new Trie();for (List<String> keywords : keywordGroups) {for (String keyword : keywords) {trie.insert(keyword);}}// 构建Trie树的失败指针,用于KMP算法trie.buildFailPointers();// 获取用户输入的文本Scanner scanner = new Scanner(System.in);System.out.print("请输入中文文本:");String userInput = scanner.nextLine();scanner.close();// 并行计算搜索组合关键词,并返回匹配的组合关键词集合Set<String> matchedCombinationKeywords = searchCombinationsParallel(userInput, keywordGroups);if (!matchedCombinationKeywords.isEmpty()) {System.out.println("匹配的组合关键词:");for (String keyword : matchedCombinationKeywords) {System.out.println(keyword);}} else {System.out.println("没有匹配到组合关键词。");}}/*** 并行计算:在文本中搜索组合关键词,并返回匹配的组合关键词集合* @param text* @param keywordGroups* @return* @throws InterruptedException* @throws ExecutionException*/public static Set<String> searchCombinationsParallel(String text, List<List<String>> keywordGroups) throws InterruptedException, ExecutionException {// 获取可用处理器核心数,并创建对应数量的线程池int numThreads = Runtime.getRuntime().availableProcessors();ExecutorService executorService = Executors.newFixedThreadPool(numThreads);// 使用线程安全的集合来保存匹配结果Set<String> matchedCombinationKeywords = new ConcurrentSkipListSet<>();// 创建并行任务列表List<Callable<Set<String>>> tasks = new ArrayList<>();for (List<String> keywords : keywordGroups) {tasks.add(() -> {Set<String> matchedKeywords = new HashSet<>();generateCombinations(text, keywords, new StringBuilder(), matchedKeywords);return matchedKeywords;});}// 并行执行任务,获取结果并合并到结果集合List<Future<Set<String>>> futures = executorService.invokeAll(tasks);for (Future<Set<String>> future : futures) {matchedCombinationKeywords.addAll(future.get());}// 关闭线程池executorService.shutdown();return matchedCombinationKeywords;}/*** 生成所有组合关键词,并在文本中查找匹配 * @param text* @param keywords* @param currentCombination* @param matchedKeywords*/private static void generateCombinations(String text, List<String> keywords, StringBuilder currentCombination, Set<String> matchedKeywords) {int[] indices = new int[keywords.size()]; // 记录每组关键词的索引while (true) {StringBuilder currentCombinationKeyword = new StringBuilder();// 生成当前的组合关键词for (int i = 0; i < keywords.size(); i++) {String keyword = keywords.get(i);// int index = indices[i];if (currentCombinationKeyword.length() > 0) {currentCombinationKeyword.append(",");}currentCombinationKeyword.append(keyword);indices[i]++;}Trie trie = new Trie();for (String keyword : currentCombinationKeyword.toString().split(",")) {trie.insert(keyword);}trie.buildFailPointers();Set<String> matched = trie.search(text);if (!matched.isEmpty()) {matchedKeywords.addAll(matched);}// 移动索引,类似组合数学中的组合生成算法int j = keywords.size() - 1;while (j >= 0 && indices[j] == keywords.size()) {indices[j] = 0;j--;}if (j < 0) {break;}}}
}

以上为java关键词组匹配程序,如果有啥不足欢迎支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/20570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

剑指 Offer 53 - I. !!在排序数组中查找数字 I (考查二分法)

剑指 Offer 53 - I. 在排序数组中查找数字 I 统计一个数字在排序数组中出现的次数。 示例 1: 输入: nums [5,7,7,8,8,10], target 8 输出: 2 示例 2: 输入: nums [5,7,7,8,8,10], target 6 输出: 0 提示&#xff1a; 0 < nums.length < 105 -109 < nums[i] &l…

day49-Todo List(待办事项列表)

50 天学习 50 个项目 - HTMLCSS and JavaScript day49-Todo List&#xff08;待办事项列表&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" co…

Ajax_02学习笔记(源码 + 图书管理业务 + 以及 个人信息修改功能)

Ajax_02 01_Bootstrap框架-控制弹框的使用 代码 <!-- 引入bootstrap.css --> <link href"https://cdn.jsdelivr.net/npm/bootstrap5.2.2/dist/css/bootstrap.min.css" rel"stylesheet"><button type"button" class"btn btn…

nlohmann::json 中文乱码解决方案

// UTF8字符串转成GBK字符串 std::string U2G(const std::string& utf8) {int nwLen MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);wchar_t* pwBuf new wchar_t[nwLen 1];//加1用于截断字符串 memset(pwBuf, 0, nwLen * 2 2);MultiByteToWideChar(CP_U…

hadoop 3.1.3集群搭建 ubuntu20

相关 hyper-v安装ubuntu-20-server hyper-v建立快照 hyper-v快速创建虚拟机-导入导出虚拟机 准备 虚拟机设置 采用hyper-v方式安装ubuntu-20虚拟机和koolshare hostnameiph01192.168.66.20h02192.168.66.21h03192.168.66.22 静态IP 所有机器都需要按需设置 sudo vim /e…

C语言技巧 ----------调试----------程序员必备技能

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; &#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382;…

【css】nth-child选择器实现表格的斑马纹效果

nth-child() 选择器可以实现为所有偶数&#xff08;或奇数&#xff09;的表格行添加css样式&#xff0c;even&#xff1a;偶数&#xff0c;odd&#xff1a;奇数。 代码&#xff1a; <style> table {border-collapse: collapse;width: 100%; }th, td {text-align: cente…

MySQL 判断字段是否包含数字或者纯数字

使用mysql原生函数FIND_IN_SET查询包含某个数字 select * from text where find_in_set(1,name) 使用regexp正则匹配纯数字 select * from text where (name REGEXP [^0-9.])0; 当 REGEXP ‘[^0-9.]’ 结果为 0 ,代表为纯数字 当 REGEXP ‘[^0-9.]’ 结果为1 ,代表不为纯数…

kube-state-metrics暴露k8s中的监控指标

kube-state-metrics 是一个用于从 Kubernetes 集群中生成各种资源对象状态指标的工具。 通过Deployment等配置完成安装 https://github.com/kubernetes/kube-state-metrics/tree/main/examples/standard 根据官方给定的配置添加至k8s上 注意需要RBAC授权 启动项 要使 kube…

在C语言中内嵌汇编语言

在C语言中内嵌的汇编指令包含大部分的ARM和Thumb指令&#xff0c;不过其使用与汇编文件中的指令有些不同&#xff0c;存在一些限制&#xff0c;主要有以下几个方面&#xff1a; &#xff08;1&#xff09;不能直接向PC寄存器赋值&#xff0c;程序跳转要使用B或者BL指令&#x…

Promise用法

学习了promise之后&#xff0c;有点懂但让我说又说不出来&#xff0c;参考别人的记录一下。 1.什么是promise&#xff1f; 2.promise解决了什么问题 3.es6 promise语法 &#xff08;1&#xff09;then链式操作语法 &#xff08;2&#xff09;catch的语法 &#xff08;3&#xf…

Git Bash 教程!【不是所有人都会用Git】

我不太会用github...... 写这篇文章希望能顺利...... 【写在前面】介绍一下git bash的复制粘贴的快捷键&#xff0c;以防后续不会&#xff1a; 开始&#xff1a; 首先下一个windows&#xff1a;git for windows(地址&#xff1a;Git - Downloading Package (git-scm.com)) &a…

P3957 [NOIP2017 普及组] 跳房子

[NOIP2017 普及组] 跳房子 题目背景 NOIP2017 普及组 T4 题目描述 跳房子&#xff0c;也叫跳飞机&#xff0c;是一种世界性的儿童游戏&#xff0c;也是中国民间传统的体育游戏之一。 跳房子的游戏规则如下&#xff1a; 在地面上确定一个起点&#xff0c;然后在起点右侧画…

基于遗传算法的试题组卷(二)

实例讲解 一、准备工作 1、问题实体 问题实体包含编号、类型&#xff08;类型即题型&#xff0c;分为五种&#xff1a;单选&#xff0c;多选&#xff0c;判断&#xff0c;填空&#xff0c;问答&#xff0c; 分别用1、2、3、4、5表示&#xff09;、分数、难度系数、知识点。一…

【MySQL】触发器 (十二)

🚗MySQL学习第十二站~ 🚩本文已收录至专栏:MySQL通关路 ❤️文末附全文思维导图,感谢各位点赞收藏支持~ 一.引入 触发器是与表有关的数据库对象,作用在insert/update/delete语句执行之前(BEFORE)或之后(AFTER),自动触发并执行触发器中定义的SQL语句集合。它可以协助应…

解决Win11右键菜单问题

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; 程序日常 ✨特色专栏&…

【MyBatis】 框架原理

目录 10.3【MyBatis】 框架原理 10.3.1 【MyBatis】 整体架构 10.3.2 【MyBatis】 运行原理 10.4 【MyBatis】 核心组件的生命周期 10.4.1 SqlSessionFactoryBuilder 10.4.2 SqlSessionFactory 10.4.3 SqlSession 10.4.4 Mapper Instances 与 Hibernate 框架相比&#…

【HAL库】STM32CubeMX开发----STM32F407----LAN8720A----移植FreeModbus实现ModbusTCP

前言 本次实验以 STM32F407VET6 芯片为MCU&#xff0c;使用 25MHz 外部时钟源。 以太网PHY层芯片为 LAN8720A&#xff0c;移植FreeModbus实现ModbusTCP网口通信。 具体内容参考文章&#xff1a;【HAL库】STM32CubeMX开发----STM32F407----ETHLAN8720ALWIP----ping通 本次移植…

零基础强化学习入门分享

&#xff08;一&#xff09;前言&#xff1a;强化学习入门顺序。 以前主要学习硬件PCB单片机等知识&#xff0c;后来接触的项目也大多与电气相关&#xff0c;从一窍不通到稍微找到点门道&#xff0c;中间走过不少弯路&#xff0c;误打误撞中&#xff0c;也留下了一些经验。 我的…

微服务——elasticsearch

初识ES——什么是elasticsearch elasticsearch的发展 初识ES——正向索引和倒排索引 初识ES——es与mysql的概念对比 类比到mysql中是表结构约束 概念对比 初始ES——安装es和kibana 1.部署单点es 1.1创建网络 要安装es容器和kibana容器并让他们之间相连&#xff0c;这里…