2014-09-20 151 views
1

我打算在Java中使用REGEX来匹配字符串。例如我有字母'A' 'A' 'A' 'P' 'P' 'L' 'E' 'S'如何匹配字符串中的特定字符n-m次

我想检查一个字符串是否包含0-3 'A', 0-2 'P', 0-1 'L', 0-1 'E' and 0-1 'S'。字符串的

例子,其应通过检查: APPLE, APPLES, ALE, PALE... etc

这是我已经试过:

if (str.matches("[A]{0,3}[P]{0,3}[L]{0,1}[E]{0,1}[S]{0,1}")) 

APPLES通过检查顺利通过,但不SAPPLE

回答

1

你正在对你的信件施加一个特定的顺序(在P之前的P之前的A之前的E,这就是为什么APPLES通过而不是SAPPLE)。其实,我不确定你想要做什么甚至可以用合理的短正则表达式。我会用一个单独的循环和一个Map来手动计算出现次数。

+0

你知道如何去除我的代码中的特定顺序吗?我可以使用循环的传统方式,但我认为它可能不是很有效,因为我有可能从字典中检索超过50,000个单词。 – user3437460 2014-09-20 01:55:21

+0

除非你的代码在洗衣机上运行,​​否则5万字是花生。如果没有循环,你认为正则表达式是如何匹配的? – Thomas 2014-09-20 06:45:45

3
(?!(.*A){4,})(?!(.*P){3,})(?!(.*L){2,})(?!(.*E){2,})(?!(.*S){2,})^[APLES]*$ 

试试这个。这将适用于你。参见演示。

http://regex101.com/r/sH6aF3/2

它使用负前瞻,以确保

A不该来先行的保证其他conditions.In结束的4个或更多times.Similarly休息时只选择了它的时间消耗串[]内的字符是允许的。

+0

我甚至没有...但是你是对的,这是正确的。如果你添加了关于它是如何工作的解释,OP可能会有所帮助。 +1来回答这个问题,但是一个正则表达式可能仍然是错误的方式。 – Thomas 2014-09-20 06:45:13

2

优化的vks's regex版本:

^(?!(?>[^A]*A){4})(?!(?>[^P]*P){3})(?!(?>[^L]*L){2})(?!(?>[^E]*E){2})(?!(?>[^S]*S){2})[APLES]*$ 

变化:

  • 感动^锚前面。
  • 将捕获组更改为原子组以防止回溯 - 当字符串不匹配时可能会大幅提升性能。
  • 使用[^A]*A等组代替.*回溯以有效地滚动匹配。

这是regex demo

+0

仍然有很多学习离我4 :) – vks 2014-09-20 07:24:04

+0

这是如此酷:) thanx。将通过他们 – vks 2014-09-20 07:29:33

+1

我怎么能监督这个看起来很熟悉的谜语:]你计算步骤似乎确实更高效,而@ vks'更紧凑一点,[我的](http:///regex101.com/r/iR2hI2/1)将再次成为关于效率的事情。那么没有测试那么多。 – 2014-09-21 05:30:26