将字符串“标记”为所需字符串的最佳方法

时间:2018-10-01 20:42:10

标签: python string python-3.x algorithm

所以,我正在寻找一种解决以下问题的算法:

为您提供所需的字符串 s 和图章 t t 也是一个字符串。令开始的字符串为len(s)*"?"

是否可以使用图章使用图章将起始字符串转换为字符串s?整个图章必须位于开头的字符串内(图章的边界不得超过????? ...字符串的边界)。

打印所需的图章数量,并为每个图章打印图章的左边框。

示例:

AABCACA (desired result)

ABCA (stamp)

Solution:
3
1 4 2
explanation: ??????? → ABCA??? → ABCABCA → AABCACA.

我的解决方案: 如果图章的首字母不是所需字符串的首字母,则无法执行此任务。最后一个字母也是如此。如果图章没有在所需字符串中包含所有字母,则该任务是不可能的。

我的算法是这样的:尝试在所需的字符串中找到图章。如果找到它,请将其删除并用问号替换。标记图章的左边框。尽可能做到这一点。

然后查找大小为len(stamp)-1的图章的连续子数组。如果发现其中任何一个,请将其删除并替换为问号。标记图章的左边框。

然后查找大小为len(stamp)-2的图章的连续子数组。如果发现其中任何一个,请将其删除并替换为问号。标记图章的左边框。这样做直到完成。在那里,你有答案。

问题 我不确定我的代码有什么问题,因为它似乎无法通过一些测试用例。可能是一个逻辑错误。

import sys

desiredString = input()
stamp = input()
stampingSpots = []

if (len(set(desiredString)) != len(set(stamp)) or stamp[0] != desiredString[0] or stamp[-1] != desiredString[-1]):
    print("-1")
    sys.exit()


def searchAndReplace(stringToFind, fix): #Search for stringToFind and replace it with len(stringToFind)*"?". Fix is used to fix the position.
    global desiredString
    for x in range(0, len(desiredString)-len(stringToFind)+1):
        if desiredString[x:x+len(stringToFind)] == stringToFind:
            stampingSpots.append(x+1-fix) #Mark down the stamping spot
            firstPart = desiredString[:x]
            firstPart += len(stringToFind)*"?"
            firstPart += desiredString[len(firstPart):]
            desiredString = firstPart
            return True
    return False

while(searchAndReplace(stamp,0)): #Search for the full stamp in desiredString
    searchAndReplace(stamp,0)



length = len(stamp)-1
while(length > 0):
    for firstPart in range(0, len(stamp)-length+1):
        secondPart = firstPart+length
        while(searchAndReplace(stamp[firstPart:secondPart], firstPart)):
            searchAndReplace(stamp[firstPart:secondPart], firstPart)

    if len(stampingSpots) > 10*len(desiredString): #Too much output, not possible
        print("-1")
        sys.exit()
    length -= 1


print(len(stampingSpots))    
for i in reversed(stampingSpots):
    print(i, end = " ")

2 个答案:

答案 0 :(得分:4)

您描述的算法从根本上来说是有缺陷的。它产生的结果与图章实际可以做的事情完全不符。例如,使用图章AB和字符串AAA,它将尝试在字符串的边界之外盖章以应用最后的A。它还将尝试将图章AB的{​​{1}}和BC子字符串彼此直接用于字符串ABC,但图章的实际应用不能做到这一点。

图章不能用于应用图章字符串的任意子字符串。它可以用于在以前的图章应用程序上盖章,但是您的算法没有考虑过盖章的全部复杂性。另外,即使您可以标记图章字符串的任意子字符串,也没有证明算法会最小化图章应用程序。

答案 1 :(得分:0)

我们可以使用分而治之:让f(s)代表生成字符串s所需的最小标记,其中“ *”是通配符。然后:

  • 吉利地挑选与图章最大匹配的字符串部分。

  • 将该部分设置为通配符,并将其左右部分分别提供给f

例如:

AABCACA (desired result)
ABCA (stamp)

f(AABCACA)
   ^^^^
   ABCA (match)

= 1 + f(A****) + f(****CA)

=> f(A****)
     ^^^^
     ABCA (match)

=> f(****CA)
       ^^^^
       ABCA

Total 3