我可以使一个正则表达式完全匹配一个类中的每个字符 - 即使字符在类中重复?

Posted

技术标签:

【中文标题】我可以使一个正则表达式完全匹配一个类中的每个字符 - 即使字符在类中重复?【英文标题】:Can I make a regex match each character in a class EXACTLY ONCE - even when characters REPEAT in the class? 【发布时间】:2020-09-28 01:21:05 【问题描述】:

我正在尝试通过一组测试,以在 Java 中使用我的正则表达式查找字谜。 只有当输入字符串中的每个字符都只使用一次时,如果一个或多个字符在输入中出现多次,是否有办法使正则表达式匹配?

给定输入字符串terror,我需要匹配rorret,而不是rottet。前两个单词完全共享所有字母,而第三个单词有三个“t”而不是三个“r”。

我目前使用的模式是(?i)^(?!terror)[terror]6

方法如下:

    private String baseString;

    public String isAnagram(String candidate) 

        Pattern p = Pattern.compile("(?i)^(?!"+baseString+")["+baseString+"]"+baseString.length()+"");

        (p.matcher(candidate).matches()) ? return candidate: return "Not an anagram.";

我尝试过负前瞻:^(?!.*?([terror]).*?\1)(?!terror)[terror]6

虽然这可以确保每个字符至少使用一次,但它不能解释 baseString 和候选字符中的重复字母。

虽然我当然知道这可以通过编程方式解决,但稍微扩展模式以适应我需要的最后一个条件会更好。

【问题讨论】:

这是一个字谜问题,单纯的正则表达式可能无法提供解决方案。 'terror' 为例,简单地对字母进行排序以形成数组["e", "o", "r", "r", "r", "t"] 然后对每个字谜候选者执行相同操作以查看它等于该数组会更容易。或者(看起来更有效),构造一个散列,给出'terror'"t"=>1, "e"=>1, "r"=>3, "o"=>1 中每个唯一字母的计数,然后对每个 anagram 候选者执行相同操作,以查看该散列是否结果。 好的,谢谢蒂姆和卡里。我现在将放弃正则表达式,伤心欲绝,并考虑构造一个哈希......我正在寻找一个有趣的解决方案和一个了解更多关于 Java 的机会,所以这似乎是合适的。 【参考方案1】:

就真正的正则表达式而言,底层的有限状态机需要 ~2ⁱ 状态(其中 i 是字符串中的字母数,假设它们都是不同的);它需要跟踪是否看到每个字母,以存储 i 位。

但是,我看不出如何用正则表达式语法来编写它;最好是受到它的启发,但手动实现它。搜索字符串中没有重复,可以只扫描一次文本(就像真正的正则表达式一样);不过,我看不出如何将其概括为具有重复字母的搜索字符串。

【讨论】:

嘿@sabik,谢谢您的意见。虽然性能对我的用例来说不是问题,但考虑机器正在完成的实际工作当然总是很有价值的。我也喜欢你所说的被正则表达式“启发”,但不使用它,我可能会那样做。不过,对于这种模式还是有点遗憾......:P

以上是关于我可以使一个正则表达式完全匹配一个类中的每个字符 - 即使字符在类中重复?的主要内容,如果未能解决你的问题,请参考以下文章

否定字符类中的单引号

如何获得完全匹配忽略正则表达式中的非数字?

如果字符串完全符合定义,则匹配正则表达式

正则表达式 - 匹配整个字符串,除非 [重复]

正则表达式

如何用正则表达式匹配连字符?