如何实现基于NFA和DFA的正则表达式匹配算法来查找所有匹配项?

时间:2012-02-20 09:10:12

标签: regex dfa nfa

匹配可以重叠。

但如果从同一位置开始发现多个匹配,请选择较短的匹配。

例如,要在字符串“abcabdcd”中找到regexp parttern “a。* d”,答案应为{“abcabd”“abd”}。并且不应包括“abcabdcd”“abdcd”

2 个答案:

答案 0 :(得分:0)

这个功能效率很低,但它解决了你的问题:

def find_shortest_overlapping_matches(pattern, line):
        pat=re.compile(pattern)
        n=len(line)
        ret=[]
        for start in xrange(0, n):
                for end in xrange(start+1, n+1):
                        tmp=line[start:end]
                        mat=pat.match(tmp)
                        if mat is not None:
                                ret.append(tmp)
                                break
        return ret

print find_shortest_overlapping_matches("a.*d", "abcabdcd")

输出:

['abcabd', 'abd']

范围假设您的模式至少包含一个字符且与空字符串不匹配。此外,您应该考虑使用?使您的模式非贪婪地匹配,以提高性能并避免内循环。

答案 1 :(得分:0)

大多数RE引擎仅默认匹配一次RE,并且默认情况下贪婪,并且围绕它们构建的标准迭代策略倾向于在上一次匹配的 end 之后重新开始搜索。要做到这一点需要一些额外的诡计。 (这段代码是Tcl,但您应该可以用许多其他语言复制它。)

proc matchAllOverlapping {RE string} {
    set matches {}
    set nonGreedyRE "(?:${RE}){1,1}?"
    set idx 0
    while {[regexp -indices -start $idx $nonGreedyRE $string matchRange]} {
        lappend matches [string range $string {*}$matchRange]
        set idx [expr { [lindex $matchRange 0] + 1 }]
    }
    return $matches
}
puts [matchAllOverlapping a.*d abcabdcd]