You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

能否仅用正则表达式查找最长前后缀重叠子串?

如何用单个正则表达式找出同时作为前缀和后缀的最长重叠子串?

先明确核心需求:我们要找字符串里最长的子串S,满足三个条件:

  • S是原字符串的前缀
  • S是原字符串的后缀
  • S在原字符串的中间位置至少出现一次(允许重叠,但不能只在开头和结尾存在)

比如你给出的例子:

  • aabaaabaaaaab里,最长符合要求的是aab
  • babababab里,最长的是babab
  • xyzxyzxyzxyzxyz里,最长的是xyzxyzxyz

你之前用的通用正则r'(?=((\w+).*\2.*\2))'是找出现三次的子串,没针对「必须是前缀+后缀」的场景优化,加^$锚点没找对方向;自己写的代码逻辑没问题,但频繁调用text.find拖慢了性能,确实挺闹心的。

解决方案:针对性优化的正则表达式

我们可以直接写一个锚定前缀和后缀的正则,同时保证子串在中间出现过,全程不需要额外的find调用,性能会提升很多。

先上可运行的代码:

import re

def get_longest_valid_substring(text):
    # 核心正则:精准匹配「前缀=后缀且中间存在」的子串
    pattern = r'^(?=(.+))(?=.*\1(?!$)).*\1$'
    longest_sub = ""
    # 遍历所有匹配的候选子串,保留最长的那个
    for match in re.finditer(pattern, text):
        candidate = match.group(1)
        # 排除整个字符串本身的情况(如果不需要排除可去掉此判断)
        if len(candidate) > len(longest_sub) and len(candidate) < len(text):
            longest_sub = candidate
    return longest_sub

# 测试你的示例文本
test_texts = [
    "aabaaabaaaaab",
    "babababab",
    "xyzxyzxyzxyzxyz"
]

for txt in test_texts:
    result = get_longest_valid_substring(txt)
    print(f"字符串「{txt}」的最长匹配子串:{result}")

正则逻辑拆解

这个正则的每一部分都是为你的需求量身定做的:

  • ^:锚定字符串开头,确保我们捕获的是前缀子串
  • (?=(.+)):正向预查,捕获从开头开始的任意长度子串(即候选S)
  • (?=.*\1(?!$)):关键的正向预查,确保\1(候选S)在字符串里出现过,且不在结尾位置(保证它在中间存在)
  • .*\1$:锚定字符串结尾,确保候选S是原字符串的后缀

正则引擎会自动匹配所有符合条件的前缀子串,我们只需要在遍历过程中保留最长的那个即可,全程不需要额外调用find,性能自然上来了。

补充说明

如果你的需求允许把整个字符串本身作为结果(比如字符串是aaaaa,此时最长匹配就是aaaaa),只需要去掉代码里的len(candidate) < len(text)判断即可。

内容的提问来源于stack exchange,提问作者Kali User

火山引擎 最新活动