查找重叠子串的多个匹配项

Posted

技术标签:

【中文标题】查找重叠子串的多个匹配项【英文标题】:find multiple matches of overlapping substrings 【发布时间】:2017-05-01 06:53:57 【问题描述】:

我正在尝试查找重叠字符串的多个匹配项,并带有单词边界。一旦找到一个子串,它就不会被考虑用于未来的匹配,即下一次搜索将在该子串的结尾之后开始。例如,我需要此字符串的这些匹配项:

pattern: "ab ab"
string: "ab ab abxxxab ab ab"
         -----         -----
                    ^ ignore this, since it is not a word boundary
substr found: (0 4)
substr found: (14 18)

我编写了以下代码,但它只找到第一个子字符串。问题是在拒绝第二个匹配后(由于单词边界),它没有找到第三个匹配,这将是一个合法的子字符串。

我得到的输出如下:

string is 0 18<ab ab abxxxab ab ab>
    match found:start=0 end=4
        substr found: (0 4)
string is 5 18<ab ab abxxxab ab ab>
    match found:start=0 end=4
    match found:start=11 end=15

(1) 如何解决此正则表达式中的问题,以便也考虑第 3 次匹配? (2) 我正在使用显式 C 代码处理字边界检查,这可以作为正则表达式本身的一部分来完成吗?

#include <iostream>
#include <string>
#include <regex>
using namespace std;
int find_substr(string str, regex pat, int start) 
        int last = str.length() - 1;
    printf("string is %d %d<%s>\n", start, last, str.c_str());
    for(auto it = sregex_iterator(str.begin(), str.end(), pat);
            it != sregex_iterator(); ++it) 
        int idx = it->position();
        int end = idx+ it->length() - 1;
        printf("match found:start=%d end=%d\n", idx, end);
        if(idx<start) 
            continue; //ignore matches before the start index
        
        if(idx>0) 
            if((str.at(idx-1)>='a' && str.at(idx-1)<='z') ||
                       (str.at(idx-1)>='A' && str.at(idx-1)<='Z')) 
                continue; // not a word boundary, ignore
            
        
        if(end<last) 
            if((str.at(end+1)>='a' && str.at(end+1)<='z') ||
                       (str.at(end+1)>='A' && str.at(end+1)<='Z')) 
                continue; // not a word boundary, ignore
            
        
        printf("substr found: (%d %d)\n", idx, end);
        return end+1;
    
    return -1;

int main() 
    string str;
    regex pat;
    int next;
    str = "ab ab abxxxab ab ab";
    pat = "ab ab";
    next = find_substr(str, pat, 0);
    if(next>0 && next<str.length()) 
        find_substr(str, pat, next);
    

【问题讨论】:

【参考方案1】:

这就是你要找的吗? \bab ab\b.

https://regex101.com/r/DtjGrN/1

这可能需要 Boost (?),因为我不知道 c++ 中的标准正则表达式库是否支持 \b

【讨论】:

不,这不起作用。在同一个代码中,我只是更改了 pat = "\bab ab\b"。没有找到一个匹配项。我正在寻找一个没有提升的解决方案。 对不起,之前的评论。有用。我将 pat 更改为“\\bab ab\\b”。它无需提升即可工作。

以上是关于查找重叠子串的多个匹配项的主要内容,如果未能解决你的问题,请参考以下文章

九度OJ 1535 重叠的最长子串

POJ 3261 Milk Patterns ( 后缀数组 && 出现k次最长可重叠子串长度 )

可重叠最长重复子串

替换字符串中的重叠匹配项(正则表达式或字符串操作)

串串的模式匹配算法(子串查找)BF算法KMP算法

Codeforces Round #545 (div 1.)