使用正则表达式查找字符串中的子词

时间:2017-08-13 10:43:40

标签: python regex python-3.x

在尝试使用Python 3解决this challenge(我在这个问题的底部粘贴)时,下面提出的两个解决方案中的第一个通过了所有测试用例,而第二个没有通过测试用例。因为在我看来,他们做的几乎一样,这让我非常困惑。为什么第二块代码不起作用?
它必须是一个非常明显的东西,因为第二个失败了大多数测试用例,但是通过自定义输入,我仍然无法弄明白。

工作解决方案:

import re
import sys

lines = sys.stdin.readlines()

n=int(lines[0])
q=int(lines[n+1])

N=lines[1:n+1]
S=lines[n+2:]

text = "\n".join(N)
for s in S:
    print(len(re.findall(r"(?<!\W)(?="+s.strip()+r"\w)", text)))

破碎&#34;解决方案&#34;:

import re
import sys

lines = sys.stdin.readlines()

n=int(lines[0])
q=int(lines[n+1])

N=lines[1:n+1]
S=lines[n+2:]

for s in S:
    total=0
    for string in N:
        total += len(re.findall("(?<!\W)(?="+s.strip()+"\w)", string))
    print(total)

我们将单词字符定义为以下任何一种:

  • 英文字母(即a-z和A-Z)。
  • 十进制数字(即0-9)。
  • 下划线(即_,对应于ASCII值)。

我们将单词定义为一个或多个单词字符的连续序列,其前面和后面是一个或多个非单词字符或行终止符。例如,在字符串 I l0ve-cheese _?中,单词是 I l0ve cheese _

我们按如下方式定义子词

  • 一系列单词字符(即英文字母, 以相同的顺序出现的数字和/或下划线(即, 作为一个连续的序列)在另一个词内。
  • 仅在单词字符之前和之后。

给定由一个或多个由非单词字符分隔的单词组成的句子,处理查询,其中每个查询由单个字符串组成,。要处理每个查询,请计算所有句子中作为子词出现的次数,然后在新行上打印出现次数。

输入格式

第一行包含一个整数 n ,表示句子数。 每个后续行包含一个由非单词字符分隔的单词组成的句子。 下一行包含一个整数,表示查询的数量。 后续行的每一行都包含一个字符串,以便检查。

约束

  • 1≤n≤100
  • 1≤q≤10

输出格式

对于每个查询字符串,打印它作为所有单词中所有单词中的子单词出现的总次数。

示例输入

1
existing pessimist optimist this is
1
is

示例输出

3

解释

我们必须计算在输入句子中作为子词出现的次数:

  • 将时间作为现有的子词发生。
  • 将时间作为悲观主义的子词。
  • 将时间作为乐观主义者的一个子词。
  • 虽然是这个词的子串,但后面跟一个空白 空间;因为空格是非字母的,非数字的,而不是 下划线,我们不认为它是一个子词出现。
  • 虽然这个词的子字符串在句子中,但我们不算数 它作为一个匹配因为它在非单词之前和之后 句子中的字符(即空格)。这意味着它 并不算作子词出现。

接下来,我们将所有单词的子词的出现总和为 1 + 1 + 1 + 0 + 0 = 3 。因此,我们在新行上打印 3

1 个答案:

答案 0 :(得分:1)

  1. 如果不将字符串指定为原始字符串,则正则表达式元字符实际上会被解释为特殊的转义字符,并且模式将与您期望的不匹配。

  2. 由于您不再查看多行字符串,因此您需要将修改后的负面反馈添加到正面字符串:(?<=\w)

  3. 正如Wiktor在他的comment中提到的那样,逃避s.strip是一个好主意,这样任何可以被视为正则表达式元集的潜在字符都将被转义并逐字逐句。您可以使用re.escape(s.strip())

  4. 您的代码可以使用此更改:

    total += len(re.findall(r"(?<\w)(?=" + re.escape(s.strip()) + r"\w)", string))