2011-08-02 9 views
8

StringA = StringBと任意のポイントに挿入された別のStringCをチェックする最良の方法は何ですか?例えば文字列への挿入の検索

は、abcdefabcXYZdefを与え、私はabcXYZdefが一方の位置4.

に挿入XYZabcdefであることを見つけたい、abcdefabRSTcdXYZefを与え、私は最初の文字列を検索するを1回の挿入で2番目にすることはできません。

私はStringAの文字を両端から渡して、StringB全体をカバーしているかどうかを確認できますが、それは書くのが面倒です。 Python(これは私が取り組んでいる)でこれをやるのがやや遅く、ちょうどこれのために特別なC拡張を書くのではないでしょう。

Regexや他の標準の文字列操作関数を使って私にできることはありますか?

編集:明確にするために、StringCは完全に不明です。有効なStringCもないかもしれませんが、そうであるかどうかを知りたいです。

+3

あなたのサンプルを作った場合、それはおそらく役立つだろう文字列が短く理解しやすくなります。 –

+0

本当に書くのは面倒だと思いますか? Pythonには、部分文字列 's1 [:n] == s2 [:n]'をチェックするためのすてきなスライシングがあります。もちろんそれは驚くほど効率的ではありませんが、コードを書くのに時間がかかりません。 – phimuemue

+0

私はあなたがキャラクターごとの解決策を拒否する理由を知りません。それは数行以上のコードではないようで、純粋なPythonほど早いでしょう。 –

答えて

6

標準libに非常に過小評価宝石がdifflibです...

>>> import difflib 
>>> s = difflib.SequenceMatcher(None, "GHSKWITNIFSI", "GHSKWAGDITNIFSI") 
>>> s.get_matching_blocks()[:-1] 
[(0, 0, 5), (5, 8, 7)] 
>>> s = difflib.SequenceMatcher(None, "GHSKWITNIFSI", "GHSKWITNIFSI") 
>>> s.get_matching_blocks()[:-1] 
[(0, 0, 12)] 
+2

+1 [difflib](http://docs.python.org/library/difflib.html#sequencematcher-objects)を知らせるが結果を解釈する方法を説明するために+1 – neurino

+1

@neurino - タプルはそれぞれ一致するブロックを表します。第1の数は第1のシーケンスにおける開始オフセットであり、第2の数は第2のシーケンスにおける開始オフセットであり、最後の数は一致するブロックの長さである。 –

+0

ニース!そのライブラリーについては決して知らなかった –

0

私は分かりませんが、あなたは "編集距離"を見つけようとしています。ウィキペディアの確認:あなたはまた、ピーター・ノーヴィグのスペル訂正で見えるかもしれません

http://en.wikipedia.org/wiki/Edit_distance

http://norvig.com/spell-correct.html

は、私はあなたが必要なものを行うには、スペル訂正からコードを適応させることができると思います。

幸運。

+0

'longest common substring' – Randy

-2
strA='foor' 
strB='foobar' 
strC='ba' 

if strB.replace(strC,'') == strA: 
    print strC,' at index ',len(strB.split(strC)[0]) 

おそらく?今すぐテストしてください...

+0

アイデアは良いですが、先験的に知られている 'strC'ですか? – phimuemue

+0

良い点。編集... – krs1

+0

私はstrCが既知の価値だとは思わない - それが彼が決定しようとしていることだ。それが分かっていれば、その質問の理由はありません。 –

2

これは...ある程度のクルージングを感じていますが、それはおそらく半分しかありませんが、あなたの例の部分文字列が見つかったようです。私がテストするために、いくつかのより多くの時間と分でいくつかを修正することができますが、それはアプローチのコンセプトです:

s1 = 'GHSKWITNIFSI' 
s2 = 'GHSKWAGDITNIFSI' 

l = len(s2) - len(s1) 

for i in range(len(s1)): 
if s2[0:i] + s2[i + l:] == s1: 
    print i 
    break 

私はrange(len())の使用を好きではないが、この特定の使用シナリオでは、私はそれが適切だと思います。 1回の挿入でs1がs2に変わると挿入が行われたインデックスが印刷されます。

+0

なぜあなたはrange(len())が好きではないですか? – krs1

+1

@ krs1 - 通常は "pythonic"ではありません...通常、反復可能なものを直接反復するか、またはインデックス値を持たなければならない場合は、それらを利用可能にするために 'enumerate(iterable)'を使用しなければなりません。私が言ったように、このシナリオではおそらく適切です。 –

0
def GetInsertedString(StringA, StringB): 
    lenA = len(StringA) 
    lenB = len(StringB) 
    if lenA > lenB: 
     return None, None 
    begincount = 0 
    while begincount < lenA and StringA[begincount] == StringB[begincount]: 
     begincount += 1 
    endcount = 0 
    while endcount < (lenA - begincount) and StringA[lenA-endcount-1] == StringB[lenB-endcount-1]: 
     endcount += 1 
    if begincount + endcount != lenA: 
     return None, None 
    return begincount, StringB[begincount:begincount+lenB-lenA] 

>>> GetInsertedString('GHSKWITNIFSI', 'GHSKWAGDITNIFSI') 
(5, 'AGD') 
>>> GetInsertedString('GHSKWITNIFSI', 'GHSKWAGDTNIFSI') 
(None, None) 
0
from itertools import dropwhile 

def get_inserted_substring(s1, s2): 
    try: 
     # diff is the first index at which the strings differ 
     diff = dropwhile(lambda i: s1[i] == s2[i], xrange(len(s2))).next() 
     if s2[diff:].endswith(s1[diff:]): 
      return (diff, s2[diff:diff-len(s1)]) 
    except (StopIteration, IndexError): 
     # the strings are the same or only differ at the end 
     if len(s1) <= len(s2): 
      return (len(s1), s2[len(s1):]) 
    return (None, None) 

と例...

>>> get_inserted_substring('abcdef', 'abcXYZdef') 
(3, 'XYZ') 
>>> get_inserted_substring('abcdef', 'abRSTcdXYZef') 
(None, None) 
>>> get_inserted_substring('abcdef', 'abcdefXYZ') 
(6, 'XYZ') 
>>> get_inserted_substring('abcdef', 'XYZabcdef') 
(0, 'XYZ') 
>>> get_inserted_substring('abcdefXYZ', 'abcdef') 
(None, None)