在字符串中查找插入

时间:2011-08-02 20:47:07

标签: python regex string algorithm

检查StringA = StringB并在某个任意点插入另一个StringC的最佳方法是什么?

例如,在给定abcdefabcXYZdef的情况下,我想找到abcXYZdefabcdef并在第4位插入XYZ

另一方面,给定abcdefabRSTcdXYZef,我想找到第一个字符串不能只用一次插入就可以转换为第二个字符串。

我知道我可以从两端逐字逐句地查看StringA,并检查它是否涵盖整个StringB,但这样写起来相当繁琐。在Python(我正在工作)中执行此操作也会相当慢,我宁愿不为此编写特殊的C扩展。

我能用Regex或其他标准字符串操作函数做些聪明的事情吗?

编辑:为了澄清,StringC是完全未知的;甚至可能没有有效的StringC,我想知道是否是这种情况。

6 个答案:

答案 0 :(得分:6)

标准库中一个非常低估的宝石是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)]

答案 1 :(得分: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()),但在这个特定的使用场景中,我认为这是合适的。如果单个插入将s1转换为s2,它将打印插入发生的索引。

答案 2 :(得分:0)

我不知道,但你正试图找到“编辑距离”。检查维基百科:

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

你也可以看看Peter Norvig的拼写纠正器:

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

我认为你可以调整拼写纠正器中的代码来完成你需要的工作。

祝你好运。

答案 3 :(得分: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)

答案 4 :(得分: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)

答案 5 :(得分:-2)

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

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

可能?立即测试...