如何找到字符串1的任何字谜是字符串2的子字符串?
例如:-
弦1 = 摇摆
字符串2 = stackoverflow
因此它将返回true,因为“ rove”的字谜是“ over”,这是字符串2的子字符串
编辑时:在最坏的情况下,我的第一个答案是二次方。我将其调整为严格线性的:
这是一种基于滑动窗口概念的方法:创建一个字典,该字典由第一个字典的字母作为键,并带有对应值的字母频率计数。可以将其视为目标字典,m第二个字符串中的连续字母需要匹配,其中m第一个字符串的长度是。
m
首先处理m第二个字符串中的第一个字母。对于每个这样的字母,如果它在目标字典中作为键出现,则将其对应的值 减小 1。目标是将所有目标值驱动为0。定义discrepancy为在处理完第一个窗口后的值的绝对值之和。m字母。
discrepancy
重复执行以下操作:检查是否discrepancy == 0返回True。否则-将字符m字母放在前面,并检查它是否为目标键,如果是- 将值增加1。在这种情况下,这会将差异增加或减少1,并进行相应调整。然后获取第二个字符串的下一个字符并进行处理。检查它是否是字典中的键,如果合适,请适当调整值和差异。
discrepancy == 0
True
由于没有嵌套循环,并且每次通过主循环都只涉及几个字典查找,比较,加法和减法,因此整个算法是线性的。
Python 3实现(显示了窗口如何滑动以及调整目标计数和差异的基本逻辑):
def subAnagram(s1,s2): m = len(s1) n = len(s2) if m > n: return false target = dict.fromkeys(s1,0) for c in s1: target[c] += 1 #process initial window for i in range(m): c = s2[i] if c in target: target[c] -= 1 discrepancy = sum(abs(target[c]) for c in target) #repeatedly check then slide: for i in range(m,n): if discrepancy == 0: return True else: #first process letter from m steps ago from s2 c = s2[i-m] if c in target: target[c] += 1 if target[c] > 0: #just made things worse discrepancy +=1 else: discrepancy -=1 #now process new letter: c = s2[i] if c in target: target[c] -= 1 if target[c] < 0: #just made things worse discrepancy += 1 else: discrepancy -=1 #if you get to this stage: return discrepancy == 0
典型输出:
>>> subAnagram("rove", "stack overflow") True >>> subAnagram("rowe", "stack overflow") False
为了对其进行压力测试,我从Gutenberg项目下载了Moby Dick的全文。它有超过一百万个字符。书中提到“福尔摩沙”,因此“摩尔人”的字谜出现在白鲸的子串中。但是,毫不奇怪,在Moby Dick中没有出现“ stackoverflow”的字谜:
>>> f = open("moby dick.txt") >>> md = f.read() >>> f.close() >>> len(md) 1235186 >>> subAnagram("moors",md) True >>> subAnagram("stackoverflow",md) False
最后一次调用大约需要1秒钟来处理Moby Dick的完整文本,并验证其中没有出现“ stackoverflow”字谜。