簡體   English   中英

與 REGEX 模式不匹配的最長 substring

[英]Longest substring that doesn't match a REGEX pattern

我正在准備考試,任務如下:給定一個由英文字母大寫字母組成的字符串,找到其中最長的 substring,其中不包含QWWQ

我知道我可以做re.split或類似的事情,但我用像len(max(re.findall(...), key=len))這樣的“正則表達式匹配”表達式對我來說是一個挑戰使用split或其他方法。 有可能嗎?

為了找到所有匹配的子串,我試過這個:

list(map(lambda x: x[0], re.findall(r'(((?<!QW|WQ).)+(?!QW|WQ))', text))

但這確實匹配以WQ結尾的 substring,例如。 我該如何解決?

讓我也澄清一些事情。 假設字符串是WQABCDEFGHQW 在這種情況下,答案是QABCDEFGHQ ,因為這正是不包含WQQW的最長 substring

您可以使用

(?:[A-Z](?<!QW|WQ)(?<!Q(?=W)|W(?=Q)))+

請參閱正則表達式演示

詳情

  • (?: - 非捕獲組的開始:
    • [AZ] - 大寫 ASCII 字母
    • (?<!QW|WQ) - 如果在左側立即有QWWQ substring(即如果[AZ]匹配W (前面有Q )或Q (前面有W ))
    • (?<?Q(?=W)|W(?=Q)) - 如果在左側立即有一個Q緊跟W ,或者W緊跟Q ,則匹配失敗的負面回顧(即如果[AZ]匹配Q並且下一個字符是W ,或者如果[AZ]匹配W並且下一個字符是Q
  • )+ - 組結束,一次或多次出現。

另一種方法:

(?:(?!QW|WQ)[A-Z](?<!QW|WQ))+

請參閱此正則表達式演示 詳情

  • (?: - 非捕獲組的開始:
    • (?!QW|WQ) - 如果緊鄰右側有QWWQ substring,則匹配失敗的否定前瞻
    • [AZ] - 大寫 ASCII 字母
    • (?<!QW|WQ) - 如果在左側立即有QWWQ substring,則匹配失敗的否定后視
  • )+ - 組結束,一次或多次出現。
.?(?:.(?<!QW|WQ))*

任何單個字符都可以。 任何其他字符都可以,除非它創建 QW 或 WQ。

演示

Python 演示以及兩個拆分解決方案:

input:   'AQWBQWC':
find:   ['AQ', 'WBQ', 'WC', '']
split1: ['AQ', 'WBQ', 'WC']
split2: ['AQ', 'WBQ', 'WC']

input:   'AQWBWQC':
find:   ['AQ', 'WBW', 'QC', '']
split1: ['AQ', 'WBW', 'QC']
split2: ['AQ', 'WBW', 'QC']

input:   '':
find:   ['']
split1: ['']
split2: ['']

input:   'A':
find:   ['A', '']
split1: ['A']
split2: ['A']

input:   'Q':
find:   ['Q', '']
split1: ['Q']
split2: ['Q']

input:   'QW':
find:   ['Q', 'W', '']
split1: ['Q', 'W']
split2: ['Q', 'W']

(額外的空匹配無關緊要,就像其他非最長匹配無關緊要一樣。將被您的max(..., key=len)丟棄。)

代碼( 在線嘗試! ):

import re

find  = r'.?(?:.(?<!QW|WQ))*'
split1 = r'(?<=Q)(?=W)|(?<=W)(?=Q)'
split2 = r'(?=.(?<=QW|WQ))'

for s in 'AQWBQWC', 'AQWBWQC', '', 'A', 'Q', 'QW':
    print('input:  ', repr(s) + ':')
    print('find:  ', re.findall(find, s))
    print('split1:', re.split(split1, s))
    print('split2:', re.split(split2, s))
    print()

你可以使用

(?:(?!Q(?!W)|(?<!W)Q).)+

Python 示例

import re

s = "HAKSDUWQHUPHPSAHFPUAHPUSNFJHJWQHPJQWPHJWQWASDIAS"
print(max(re.findall(r"(?:(?!Q(?!W)|(?<!W)Q).)+", s), key=len))  # 'HUPHPSAHFPUAHPUSNFJHJW'

請參閱正則表達式演示

你可以使用它(?:(?.WQ|QW)?(?<!WQ|QW))+

在每個 position(點)處,如果字符不是 WQ 或 QW 的一部分,它會向前和向后測試。

關鍵是在position點之前向前測試,在點之后向后測試。

演示


其他可能的模式: (?:.(?.??(?<=WQ|QW)))+

這次后視是在否定前瞻中,但因為它前面有一個可選字符.? , 它檢查 WQ/QW 序列的兩個可能位置。

演示


或者減少展開模式的步驟數:
[^WQ]+(?:[QW](?.??(?<=QW|WQ))[^WQ]*)*|(:?[QW](.???(?<=QW|WQ))[^WQ]*)+

但是有點長(展開了)。

演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM