我的代码有效,我正在寻找更聪明的想法以提高效率?
对于字符串相似性,它被定义为最长公共前缀长度, 例如,“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 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
答案 0 :(得分:2)
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
答案 1 :(得分:1)
构建TrieTree
对象需要做很多工作。跳过那个。只需对匹配的所有可能起点进行双循环,以及可能仍然匹配的所有可能偏移。
如果您要多次查询数据结构,那么构建这样的复杂对象才有意义。但是你不是这样,它不会得到回报。
答案 2 :(得分:1)
以下是您可能希望考虑的3种有效方法:
计算原始字符串的后缀树。然后通过后缀树下降主路径,计算每个阶段离开校长的路径数。
计算后缀数组和最长公共前缀数组。 这些数组可用于计算任何一对足够的最长前缀,特别是原始字符串和每个后缀之间的最长前缀。
您尝试构建的输出称为Z功能。 它可以直接在线性时间内计算,如here所示(显然不是Python代码):
vector z_function(string s) {
int n = (int) s.length();
vector z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = min (r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z;
}