4

試合は重複する可能性があります。

ただし、同じ位置から始まる複数の一致が見つかった場合は、短いものを選択してください。

たとえば、文字列"abcabdcd"で正規表現部分"a.*d"を見つけるには、答えは { "abcabd" , "abd" } になります。また、「abcabdcd」「abdcd」は含めないでください。

4

2 に答える 2

0

ほとんどのREエンジンは、デフォルトでREと1回だけ一致し、貪欲に一致します。それらを中心に構築された標準の反復戦略は、前回の一致の終了後に検索を再開する傾向があります。それ以外のことをするには、いくつかの追加のトリックが必要です。(このコードは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]
于 2012-02-20T09:47:11.207 に答える
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 文字が含まれ、空の文字列と一致しないことを前提としています。さらに、?パフォーマンスを向上させ、内部ループを回避するために、パターンを非貪欲に一致させるために を使用することを検討する必要があります。

于 2012-02-20T09:27:50.430 に答える