当前位置: 首页 > 知识库问答 >
问题:

java - 前缀最优匹配算法代码实现??

乐正远
2026-01-08

前缀最优匹配算法代码实现

1. 通过跟编码字符串进行匹配, 从一个已经建立好的编码对照表里面找出最优的编码ID
2. 编码对照表定义如下:
    1. 编码字符串(长度最大为6): 1~6位的小写字母字符串
    2. 编码ID: 整数
    3. 编码字符串和编码ID都是唯一值, 没有重复
    4. 编码对照表已经按<编码字符串>排好序(升序)
    5. 编码对照表记录数: 2万左右
    6. 编码表样例: (以JSON形式来描述)
        {"a":1, "aa":2, "aab":3, "aba":4, "b", ... , "xyzabc":19800, "zab":19801, "zz":19802}
3. 前缀最优匹配算法:
        1. 从字符串的第一位开始匹配, 匹配长度最长优先
        2. 待匹配字符串的长度最短为6位
        3. 以上面的编码表为例进行匹配:
            1. "aiabcdef" 匹配记录为"a":1
            2. "aabchjhk" 匹配记录为"aab":3
            3. "aacxylm"  匹配记录为"aa":2
            4. "abcdhkd" 匹配记录为"a":1
            5. "zaaihl" 没有匹配记录:-1
        3. 匹配算法函数定义: 
            function BestFind(2万条记录的编码对照表, 需要匹配的编码字符串)
            按上面的编码表样例, BestFind($CodeMap, "aabchgl") 应该返回 3
            
4. 题目本意是设计一个高效<查找算法>, 查找执行前的数据准备时间不归入算法开销里面
5. 在2万个充分随机产生的编码表里面进行查找, 效率应该在每秒10万次以上才算合格

共有2个答案

单于奇略
2026-01-08

可以试试一下字典树 (Trie)

小牛25342
2026-01-08

以下是前缀最优匹配算法的高效实现,使用二分查找优化性能,满足每秒10万次查询的要求。算法基于已排序的编码表,从最长前缀(6位)开始尝试,逐步缩短长度,直到找到匹配或遍历完所有可能前缀。

import bisect

def best_find(keys, values, s):
    """
    前缀最优匹配算法实现
    :param keys: 已排序的编码字符串列表(升序)
    :param values: 对应的编码ID列表
    :param s: 待匹配的字符串(长度至少6位)
    :return: 匹配的编码ID(未找到返回-1)
    """
    n = len(keys)
    if n == 0 or len(s) < 1:
        return -1
    
    # 只检查前6个字符
    max_len = min(6, len(s))
    
    # 从最长前缀开始尝试(6 → 1)
    for L in range(max_len, 0, -1):
        prefix = s[:L]
        # 二分查找定位位置
        idx = bisect.bisect_left(keys, prefix)
        # 检查是否匹配
        if idx < n and keys[idx] == prefix:
            return values[idx]
    return -1

算法说明

  1. 核心逻辑

    • 从最长可能前缀(6位)向最短(1位)遍历。
    • 对每个前缀长度 L,用 bisect_left 在有序列表中二分查找。
    • 若找到完全匹配的编码字符串,立即返回对应编码ID。
  2. 时间复杂度

    • 最多尝试6次(前缀长度6→1)。
    • 每次二分查找复杂度为 $O(\log N)$,$N=20000$ 时约15次比较。
    • 总复杂度 $O(6 \times \log N) \approx O(90)$ 次操作/查询,满足每秒10万次性能要求。
  3. 空间复杂度:$O(1)$,无额外空间占用。

测试用例验证

# 编码表(keys已排序)
keys = ['a', 'aa', 'aab', 'aba', 'b', 'xyzabc', 'zab', 'zz']
values = [1, 2, 3, 4, 5, 19800, 19801, 19802]

# 测试案例
print(best_find(keys, values, "aiabcdef"))   # 输出: 1(匹配"a")
print(best_find(keys, values, "aabchjhk"))   # 输出: 3(匹配"aab")
print(best_find(keys, values, "aacxylm"))    # 输出: 2(匹配"aa")
print(best_find(keys, values, "abcdhkd"))    # 输出: 1(匹配"a")
print(best_find(keys, values, "zaaihl"))     # 输出: -1(无匹配)

性能优化关键

  1. 有序数组二分查找:利用 bisect_left 快速定位(比遍历快 $O(N/\log N)$ 倍)。
  2. 从长前缀开始匹配:优先匹配最长前缀,找到后立即返回,避免冗余检查。
  3. 最小化字符串操作:仅截取待匹配前缀,不处理超长字符串。

此实现严格满足题目要求,在2万条随机编码表下可轻松达到每秒10万次以上查询。

 类似资料:
  • 在PostgreSQL中获得最长前缀匹配的准确快速查询的最佳方法是什么? 是: 我计划在更新中使用。有什么想法吗?

  • 本文向大家介绍python正则中最短匹配实现代码,包括了python正则中最短匹配实现代码的使用技巧和注意事项,需要的朋友参考一下 下面从一个例子入手: 利用正则表达式解析下面的XML/HTML标签: 希望自动格式化重写为: composer: Wolfgang Amadeus Mozart author: Samuel Beckett city: London 一个代码是这样的形式: 这个代码运

  • 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。 示例 1: 输入: ["flower","flow","flight"] 输出: "fl" 示例 2: 输入: ["dog","racecar","car"] 输出: "" 解释: 输入不存在公共前缀。 说明: 所有输入只包含小写字母 a-z 。 话不多说,上code: /** * @param {stri

  • foo-bar-herp foo-bar-derp baz-blub其他东西 我想提供一个搜索工作,以便 “foo bar”(标记化前缀) “Foo Herp”(跳过令牌) “foo-bar-”(确切的前缀) “bar-herp”(中间的确切字符串) “foo ba”(一个完整的令牌和另一个令牌的前缀) null

  • 问题内容: 关于Java中的运算符优先级,我有两个类似的问题。 第一: 根据Oracle教程: postfix(expr ,expr–)运算符的优先级高于前缀( expr,-expr) 因此,我假设该评估顺序为: 但是Java似乎忽略了PRE / POST排序,而是将它们放在一个级别上。所以真正的顺序: 是什么导致答案为(10 * 12 * 12)= 1440。 第二个: 这个问题的例子: 可接受

  • 我遇到了一个问题,elasticsearch在我的环境(舞台和生产)中返回不同的结果。 我使用的elasticsearch版本对于这两种环境是相同的。 这两个环境都具有相同的映射和索引设置。 我有一个项目索引的标题字段为“测试”。我正在尝试执行match_phrase_prefix查询。然而,在我的舞台环境中,当我搜索“te”时,结果会像预期的那样返回。在生产中,我必须将搜索查询扩展到“TES”(

  • 本文向大家介绍PHP实现的最大正向匹配算法示例,包括了PHP实现的最大正向匹配算法示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP实现的最大正向匹配算法。分享给大家供大家参考,具体如下: 正向最大匹配算法:从左到右将待分词文本中的几个连续字符与词表匹配,如果匹配上,则切分出一个词。但这里有一个问题:要做到最大匹配,并不是第一次匹配到就可以切分的 。 函数中包含三个参数: $que

  • 本文向大家介绍Java计算器核心算法代码实现,包括了Java计算器核心算法代码实现的使用技巧和注意事项,需要的朋友参考一下 在进行一个表达式的计算时,先将表达式分割成数字和字符串然后利用出入栈将分割后的表达式进行中缀转后缀,再将后缀表达式进行计算得到结果(思想在上一篇写过)现在贴下Java语言的代码实现。(学习Java时间不长所以可能会有很多不足的地方,我会改进也欢迎大神可以给我一些意见和建议~谢