如何编写满足特定字母、频次及k长度限制的正则表达式?
用正则表达式筛选符合字母频次与长度要求的单词
要解决拼字游戏这类的字母筛选问题,核心难点是同时限制字符范围、出现频次和单词长度——普通的字符组正则(比如^[DENOOPRSU]{9}$)只会检查字符是否在允许范围内,完全忽略重复次数限制,导致出现错误结果。
实现思路
利用正则的正向预查特性,为每个字母添加频次限制,再结合字符组和长度限制,就能一次性满足所有条件:
- 先统计给定字母集合中每个字符的出现次数(比如
DENOOPRSU里O出现2次,其余字母各1次) - 对每个字符X,生成正向预查断言,限制其出现次数不超过统计值m:
(?=(?:[^X]*X){0,m}[^X]*$) - 拼接所有断言后,加上固定长度的字符组匹配,最终包裹在
^$中确保整词匹配
实例演示
针对DENOOPRSU集合筛选9字母单词
正则表达式:
^(?=(?:[^O]*O){0,2}[^O]*$)(?=(?:[^D]*D){0,1}[^D]*$)(?=(?:[^E]*E){0,1}[^E]*$)(?=(?:[^N]*N){0,1}[^N]*$)(?=(?:[^P]*P){0,1}[^P]*$)(?=(?:[^R]*R){0,1}[^R]*$)(?=(?:[^S]*S){0,1}[^S]*$)(?=(?:[^U]*U){0,1}[^U]*$)[DENOOPRSU]{9}$
这个正则会匹配PONDEROUS(符合O出现2次、其余字母各1次的要求),但会排除SPONSORED(其中S出现2次,超出集合中的频次)。
针对DENOOPRSU集合筛选7字母单词
正则表达式:
^(?=(?:[^O]*O){0,2}[^O]*$)(?=(?:[^D]*D){0,1}[^D]*$)(?=(?:[^E]*E){0,1}[^E]*$)(?=(?:[^N]*N){0,1}[^N]*$)(?=(?:[^P]*P){0,1}[^P]*$)(?=(?:[^R]*R){0,1}[^R]*$)(?=(?:[^S]*S){0,1}[^S]*$)(?=(?:[^U]*U){0,1}[^U]*$)[DENOOPRSU]{7}$
它会匹配ONEROUS,排除USURPER(U出现2次,不符合集合频次)。
通用生成方法
如果需要适配不同的字母集合和长度,只需:
- 统计目标字母的频次(这一步仅用于生成正则,不参与过滤,不影响效率)
- 替换正则中对应的频次数值和字符组内容
- 修改末尾的长度数字
{k}
这种方案相比用Collections.Counter逐个过滤单词,效率提升明显——正则引擎会在匹配阶段一次性完成所有条件校验,无需额外遍历计数。
内容的提问来源于stack exchange,提问作者koko
相关产品推荐
相关产品推荐

