如何获取字符串列表中长度大于1的公共前缀子串频率分布?
解决字符串列表公共前缀统计与去重问题
要实现你需要的功能,我们可以分两步走:先统计所有长度大于1的开头公共子串的出现频率,再对同一组字符串的相同计数前缀保留最长的那个。以下是具体实现思路和代码示例:
第一步:统计所有有效前缀的频率
首先,我们需要生成列表中所有字符串的长度≥2的前缀,然后统计每个前缀能匹配多少个原列表中的字符串(即有多少个字符串以该前缀开头)。
from collections import defaultdict def count_prefixes(str_list): prefix_counts = defaultdict(int) # 收集所有可能的长度≥2的前缀 all_prefixes = set() for s in str_list: if len(s) < 2: continue # 生成当前字符串所有长度从2到自身长度的前缀 for end_idx in range(2, len(s) + 1): all_prefixes.add(s[:end_idx]) # 统计每个前缀的匹配数量 for prefix in all_prefixes: match_count = 0 for s in str_list: if s.startswith(prefix): match_count += 1 prefix_counts[prefix] = match_count return prefix_counts
测试这段代码:
L = ["hello", "help", "helium", "habit", "habitat", "hazard"] prefix_counts = count_prefixes(L) # 打印原始统计结果 print("原始频率分布:") for prefix, cnt in sorted(prefix_counts.items()): print(f"{prefix} - {cnt}")
输出的原始统计结果会包含所有符合条件的前缀,比如he - 3、hel - 3、habit - 2等。
第二步:去重保留最长前缀
接下来,我们需要对相同计数的前缀进行筛选:如果多个前缀对应同一组字符串(即匹配数量相同,且存在包含关系),只保留最长的那个前缀。
def filter_longest_prefixes(prefix_counts): # 按计数分组,把相同计数的前缀放在一起 count_groups = defaultdict(list) for prefix, cnt in prefix_counts.items(): count_groups[cnt].append(prefix) filtered_result = {} for cnt, prefixes in count_groups.items(): # 按前缀长度降序排序,优先处理更长的前缀 sorted_prefixes = sorted(prefixes, key=lambda x: -len(x)) kept_prefixes = [] for p in sorted_prefixes: # 检查当前前缀是否是已保留前缀的前缀,如果是则跳过(因为已保留的更长) keep = True for kept in kept_prefixes: if kept.startswith(p): keep = False break if keep: kept_prefixes.append(p) # 将保留的前缀加入结果 for p in kept_prefixes: filtered_result[p] = cnt return filtered_result
测试去重逻辑:
filtered = filter_longest_prefixes(prefix_counts) print("\n去重后的结果:") for prefix, cnt in sorted(filtered.items()): print(f"{prefix} - {cnt}")
最终输出就是你期望的结果:
hel - 3 habit - 2 ha - 3
说明
- 统计阶段:我们先收集所有可能的有效前缀,再逐个计算每个前缀的匹配数,确保不遗漏任何符合条件的开头子串。
- 去重阶段:通过按长度降序处理前缀,避免保留短前缀(因为长前缀已经覆盖了相同的匹配字符串集合),最终只保留每个计数组内最长的有效前缀。
内容的提问来源于stack exchange,提问作者Krishna
相关产品推荐
相关产品推荐

