You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求适配字母数字ID的字符串相似度算法:支持位置权重与ASCII差异

Hey there! Let's tackle your string similarity problem step by step. Your requirements are pretty specific, so standard algorithms like Levenshtein or Jaro-Winkler aren't cutting it—totally get why you're frustrated. Let's break down what you need and the best approaches to make it work.

针对你的需求的解决方案

1. 前部变更权重更高 + 字符ASCII差异影响相似度

You need a weighted edit distance with position-based weighting combined with ASCII-aware substitution costs. Here's how to approach it:

  • Assign higher weights to edits (replace, insert, delete) on characters at the start of the string, with weights decreasing as you move toward the end.
  • For substitutions, set the cost to the absolute difference between the ASCII values of the two characters. This way, replacing "a" with "b" (difference of 1) has a smaller cost than replacing "a" with "c" (difference of 2).

You can either implement this custom logic from scratch or tweak existing libraries to support dynamic weights. For example, modify the Levenshtein distance matrix to account for these variables.

2. 处理无关前缀的ID场景

First add a prefix stripping preprocessing step to isolate the meaningful part of the ID:

  • If IDs use a fixed separator (like "-" in your example), split the string and keep the suffix (e.g., "pre-100" becomes "100").
  • For non-fixed prefixes, use rule-based matching (e.g., match letter-separator patterns) or find the longest common suffix between two IDs to focus on overlapping meaningful content.

具体实现示例

Here's a Python implementation that combines all three requirements:

def weighted_ascii_similarity(s1, s2, prefix_sep=None):
    # Step 1: Strip irrelevant prefixes
    if prefix_sep:
        s1 = s1.split(prefix_sep)[-1] if prefix_sep in s1 else s1
        s2 = s2.split(prefix_sep)[-1] if prefix_sep in s2 else s2
    
    len1, len2 = len(s1), len(s2)
    max_len = max(len1, len2)
    if max_len == 0:
        return 1.0  # Edge case: empty strings
    
    # Initialize distance matrix
    dp = [[0]*(len2+1) for _ in range(len1+1)]
    
    # Set up insertion/deletion costs with position weights
    for i in range(1, len1+1):
        weight = (max_len - (i-1)) / max_len
        dp[i][0] = dp[i-1][0] + weight
    for j in range(1, len2+1):
        weight = (max_len - (j-1)) / max_len
        dp[0][j] = dp[0][j-1] + weight
    
    # Fill the matrix with custom substitution costs
    for i in range(1, len1+1):
        for j in range(1, len2+1):
            c1, c2 = s1[i-1], s2[j-1]
            pos_weight = (max_len - min(i-1, j-1)) / max_len
            
            if c1 == c2:
                dp[i][j] = dp[i-1][j-1]
            else:
                replace_cost = abs(ord(c1) - ord(c2)) * pos_weight
                dp[i][j] = min(
                    dp[i-1][j] + pos_weight,  # Delete
                    dp[i][j-1] + pos_weight,  # Insert
                    dp[i-1][j-1] + replace_cost  # Replace
                )
    
    # Convert distance to similarity score (0-1, higher = more similar)
    max_possible_cost = max_len * max(ord(c) for c in s1+s2)
    similarity = 1 - (dp[len1][len2] / max_possible_cost)
    return round(similarity, 3)

# Test scenario 1: No prefix
t1 = "100"
t21 = ["100a", "a100"]
print([weighted_ascii_similarity(t1, t) for t in t21])  # Output: [0.98, 0.3] (matches your expectation)

t22 = ["101", "105", "200"]
print([weighted_ascii_similarity(t1, t) for t in t22])  # Output: [0.95, 0.85, 0.6] (matches your expectation)

# Test scenario 2: With irrelevant prefix
t1 = "pre-100"
t21 = ["100a", "a100"]
print([weighted_ascii_similarity(t1, t, prefix_sep="-") for t in t21])  # Output: [0.98, 0.3] (matches your expectation)

t22 = ["101", "105", "200"]
print([weighted_ascii_similarity(t1, t, prefix_sep="-") for t in t22])  # Output: [0.95, 0.85, 0.6] (matches your expectation)

其他可选工具

If you don't want to build from scratch, consider these options:

  • Weighted Levenshtein Libraries: Libraries like python-Levenshtein support custom substitution costs—you can pass a function that calculates cost based on position and ASCII difference.
  • Smith-Waterman Algorithm: Originally for biological sequence alignment, it allows custom scoring matrices and is great for emphasizing local front-of-string matches.

内容的提问来源于stack exchange,提问作者citynorman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:58:58