Die oben genannten Lösungen sind wirklich toll, aber wenn die Schlüsselwörter Wörterbuch kann es chaotisch werden (vielleicht unimplementable) leicht lang ist.
Ich schlage vor, die Schlüsselwörter in einem Baum zu speichern (der Redundanz ausnutzt) und ist mehr Platz effizient.
Wenn die Schlüsselwörter ["art,"at","atm","bus","can","car"]
das Wörterbuch sind wie folgt aussieht
.
^
/ ¦ \
/ ¦ \
a b c
^ ^ ^
/ \ \ \
r t u a
^ ^ ^ ^
/ /\ \ / \
t m /0 s n r
^ ^ ^ ^ ^
/ / \ \ \
/0 /0 /0 /0 /0
ich es binär gemacht, da es leichter war, zu ziehen. Der Knoten "/0"
hat die Bedeutung von Wortende (virtuelles Zeichen) und "."
ist die Wurzel.
Ich implementierte diese einfache Tree-Klasse den Baum und die notwendigen Funktionen
class Tree(object):
def __init__(self, name='root', children=None):
self.name = name
self.children = {}
if children is not None:
for child in children:
self.add_child(child.name,child)
def __repr__(self):
return self.name
def add_child(self, node):
assert isinstance(node, Tree)
self.children[node.name] = node
def has_child(self,name):
return name in self.children
def get_child(self,name):
return self.children[name]
def print_tree(self,level=0):
sys.stdout.write('-' * level)
print self.name
for childTag in self.children:
self.children[childTag].print_tree(level+1)
die Schlüsselwörter Da wir die Struktur unter Verwendung von Code wie dieser
keywords = ["car","at","atm","bus"]
keywordsTree = Tree('')
for keyword in keywords:
keywordsTreeNode = keywordsTree
for character in keyword:
if not keywordsTreeNode.has_child(character):
keywordsTreeNode.add_child(Tree(character))
keywordsTreeNode = keywordsTreeNode.get_child(character)
keywordsTreeNode.add_child(Tree('/0'))
Schließlich suchen wir den Eingang für Keywords erstellen können bauen . Die untenstehende Lösung bietet für eine gegebene Position in der Eingabe alle Schlüsselwörter, die von dieser Position ausgehend übereinstimmen.
inputWords = "xyzcarbusabccar8hj/0atm"
output = []
lengthInput = len(inputWords)
for position in range(0,lengthInput):
##add by default the character
# allMathcedKeyWords = [inputWords[position]]
allMathcedKeyWords = []
keywordsTreeNode = keywordsTree
searchPosition = position
curMathcedWord = ''
while searchPosition < lengthInput and keywordsTreeNode.has_child(inputWords[searchPosition]) :
keywordsTreeNode = keywordsTreeNode.get_child(inputWords[searchPosition])
curMathcedWord = curMathcedWord + inputWords[searchPosition]
if (keywordsTreeNode.has_child("/0")):
allMathcedKeyWords.append(curMathcedWord)
searchPosition += 1
if len(allMathcedKeyWords)==0:
allMathcedKeyWords = inputWords[position]
output.append(allMathcedKeyWords)
print output
Dieser Code gibt dieses
['x', 'y', 'z',
['car'],
'a', 'r',
['bus'],
'u', 's', 'a', 'b', 'c',
['car'],
'a', 'r', '8', 'h', 'j', '/', '0',
['at', 'atm'],
't', 'm']
Wichtig für den Code oben ist die Tatsache, dass der virtuelle Charakter am Ende der Wörter zwei Buchstaben ("/0"
) und wird nie (auch wenn die abgestimmt werden Kombination erscheint in der Eingabesequenz wie oben beschrieben). Darüber hinaus behandelt es jedes String-Zeichen (für die Eingabe und Schlüsselwörter - müssen auch keine Escape-Zeichen wie in re.findall()
)
Aus dieser Liste können Sie entscheiden, was Sie tun möchten. Wenn Sie die Lösung re.findall
möchten, finden Sie das am längsten übereinstimmende Wort für eine Position (oder basierend auf der logischen Reihenfolge der Schlüsselwörter) und springen Sie die Anzahl der Zeichen, die das Wort enthält, vor. Wenn das Problem noch weiter geht, ist jedes Zeichen in der Eingabe ein Eckpunkt, und wenn Sie ein Wort finden, fügen Sie eine Kante von dieser Position zum entsprechenden nächsten Eckpunkt nach dem letzten Zeichen des übereinstimmenden Wortes hinzu. Ein Algorithmus für den kürzesten Pfad gibt Ihnen die obige Lösung erneut. Durch die Strukturierung der Ausgabe wird die Raumeffizienz wieder erhöht und die Tür zu komplexeren Algorithmen geöffnet.
Beispiel, mit Schlüsselwörter "car"
und "art"
und Kunst und Eingangssequenz "acart"
die resultierenden Graphen
______________
¦ ¦
- a -> c -> a -> r -> t ->
¦______________¦
Komplexität Analyse
Space : longest_word_length * number_of_letters_in_keywords
input_length + input_length * input_length (worst case-fully connected graph)
Time : input_length * longest_word_length
input_length + input_length * input_length (worst case-fully connected graph)
Große Lösung sieht wie folgt aus. Mit ''[a-z] |' + '|' .join (keywords) 'würde es einfacher machen, die Regex programmatisch zu erstellen. – SuperBiasedMan
@SuperBiasedMan Danke. Es wäre ''|' .join (keywords) + '| [a-z]'' obwohl die Reihenfolge kritisch ist, weil die Regex-Engine die Alternativen von links nach rechts durchsucht und * eager * eine Übereinstimmung zurückgibt. Deshalb funktioniert die Lösung, vielleicht sollte ich in einer Erklärung editieren. – timgeb
Ah, dumme mich! Ich benutze nicht viel Regex, und ich dachte nur, dass die andere Reihenfolge besser lesbar wäre. – SuperBiasedMan