Python 更有效的子串计算方法
我的代码可以工作,我正在寻找更聪明的想法来提高效率 对于字符串相似性,定义为最长公共前缀长度, 例如,“abc”和“abd”是2,“aaa”和“aaab”是3 问题是计算字符串S及其所有后缀的相似性, 包括它自己作为第一个后缀 例如,对于S=“ababaa”,后缀是“ababaa”、“babaa”、“abaa”、“baa”、“aa” 和“a”,相似性为6+0+3+0+1+1=11Python 更有效的子串计算方法,python,algorithm,Python,Algorithm,我的代码可以工作,我正在寻找更聪明的想法来提高效率 对于字符串相似性,定义为最长公共前缀长度, 例如,“abc”和“abd”是2,“aaa”和“aaab”是3 问题是计算字符串S及其所有后缀的相似性, 包括它自己作为第一个后缀 例如,对于S=“ababaa”,后缀是“ababaa”、“babaa”、“abaa”、“baa”、“aa” 和“a”,相似性为6+0+3+0+1+1=11 # Complete the function below. from collections import def
# Complete the function below.
from collections import defaultdict
class TrieNode:
def __init__(self):
self.children=defaultdict(TrieNode)
self.isEnd=False
class TrieTree:
def __init__(self):
self.root=TrieNode()
def insert(self, word):
node = self.root
for w in word:
node = node.children[w]
node.isEnd = True
def search(self, word):
node = self.root
count = 0
for w in word:
node = node.children.get(w)
if not node:
break
else:
count += 1
return count
def StringSimilarity(inputs):
resultFormat=[]
for word in inputs:
# build Trie tree
index = TrieTree()
index.insert(word)
result = 0
# search for suffix
for i in range(len(word)):
result += index.search(word[i:])
print result
resultFormat.append(result)
return resultFormat
构建
TrieTree
对象需要大量的工作。跳过这个。只要在一个匹配的所有可能的起始点和所有可能的偏移量上做一个双循环,你可能仍然在匹配
只有在多次查询数据结构的情况下,构建这样的复杂对象才有意义。但是这里你没有,所以它没有回报。构建
TrieTree
对象需要大量的工作。跳过这个。只要在一个匹配的所有可能的起始点和所有可能的偏移量上做一个双循环,你可能仍然在匹配
def similarity(s, t):
""" assumes len(t) <= len(s), which is easily doable"""
i = 0
while i < len(t) and s[i] == t[i]:
i += 1
return i
def selfSimilarity(s):
return sum(similarity(s, s[i:]) for i in range(len(s)))
selfSimilarity("ababaa")
# 11
只有在多次查询数据结构的情况下,构建这样的复杂对象才有意义。但在这里你不是这样的,所以它不会有回报。def相似性(s,t):
def similarity(s, t):
""" assumes len(t) <= len(s), which is easily doable"""
i = 0
while i < len(t) and s[i] == t[i]:
i += 1
return i
def selfSimilarity(s):
return sum(similarity(s, s[i:]) for i in range(len(s)))
selfSimilarity("ababaa")
# 11
“”“假定len(t)def相似性(s,t):
“假设len(t)以下是您可能希望考虑的三种有效方法:
后缀树
计算原始字符串的后缀树。然后通过后缀树沿着主路径下降,计算每个阶段偏离主路径的路径数
后缀数组
计算后缀数组和最长的公共前缀数组。
这些数组可用于计算任何一对后缀的最长前缀,尤其是原始字符串和每个后缀之间的最长前缀
Z函数
您试图构造的输出称为Z函数。
它可以在线性时间内直接计算,如图所示(显然不是Python代码):
向量z_函数(字符串s){
int n=(int)s.length();
向量z(n);
对于(int i=1,l=0,r=0;i
以下是您可能希望考虑的三种有效方法:
后缀树
计算原始字符串的后缀树。然后通过后缀树沿着主路径下降,计算每个阶段偏离主路径的路径数
后缀数组
计算后缀数组和最长的公共前缀数组。
这些数组可用于计算任何一对后缀的最长前缀,尤其是原始字符串和每个后缀之间的最长前缀
Z函数
您试图构造的输出称为Z函数。
它可以在线性时间内直接计算,如图所示(显然不是Python代码):
向量z_函数(字符串s){
int n=(int)s.length();
向量z(n);
对于(int i=1,l=0,r=0;i
我认为你的问题更适合安德里亚,但我建议,安德里亚是对的。@Rockybilly,我认为编辑距离与我的问题不同?我只需要检查前缀。谢谢。我建议你稍微修改一下措辞,使用“substring”而不是“suffix”,因为suffix仅表示单词的开头,子字符串意味着字符串的一小部分可能出现在string@Rockybilly-我认为这只是一个带有人为字符串相似性的编码挑战:我认为你的问题更适合Andrea是对的,但是,我建议。@Rockybilly,我认为编辑距离与我所问的不同?我只需要检查前缀。谢谢。我建议您稍微修改一下措辞,使用“substring”而不是“suffix”,因为suffix仅表示单词的开头,substring表示字符串的一小部分,它可能会出现在文本中的任何位置string@Rockybilly-我认为这只是一个具有人为字符串相似性的编码挑战:谢谢你,为什么你的方法比我的Trie树快?:)我实际上没有机会使用你的方法,所以我不能肯定。一个潜在的问题是开销-而不是使用str
,这是一个内置的、非常轻量级的;每个后缀的每个字母都是一个trieode
,它有一个defaultdict
,它有一个键和值,这是另一个trieode
。。。这需要大量的对象实例化和创建(从而取消引用),而不是一个字母一个字母地strcmp
。正如@btilly所提到的-您没有重用任何TrieNode
s,因此它更简单。只进行直接测试更快。显然,实际上是高效的实现(可能是@Peter di Rivaz所建议的,尽管那里的信息非常缺乏):谢谢dwanderson,我读了参考资料,做了更多的分析,特别是被一点弄糊涂了。我认为有可能存在另一个l2,其中值z[I-l2]大于z[I-l],甚至可以跳过更多元素进行比较,子字符串[l2…r2]不一定像子字符串[l…r]那样是最匹配的段。谢谢您的评论。@LinMa希望我能帮忙,但我自己并不知道Z算法
;我刚找到链接,它似乎很相关:)。谢谢你,为什么你的方法比我的Trie树快?:)我实际上没有机会使用你的方法,所以我不能肯定。一个潜在的问题是开销-而不是使用str
,这是一个内置的、非常轻量级的;每个后缀的每个字母都是一个trieode
,它有一个defaultdict
,它有一个键和值,这是另一个trieode
。。。这需要大量的对象实例化和创建