Non sono sicuro se sia una buona idea combattere questo problema. Se una persona vuole mettere delle cianfrusaglie in un campo comune, verrà sempre in mente l'idea di come farlo. Ma voglio ignorare questo fatto e combattere il problema come una sfida algoritmico:
Avere una stringa S, che consiste delle stringhe (che può apparire molte volte e non si sovrappongono) trovare la stringa che consiste di.
La definizione è pidocchio e presumo che la stringa sia già stata convertita in lettere minuscole.
Prima un modo più semplice:
Uso modifica di un longest common subsequence che ha una semplice soluzione di programmazione DP. Ma invece di trovare una sottosequenza in due sequenze diverse, è possibile trovare la sottosequenza comune più lunga della stringa rispetto alla stessa stringa LCS(s, s)
.
Sembra stupido all'inizio (sicuramente LCS(s, s) == s
), ma in realtà non ci interessa la risposta, ci interessa la matrice DP che ottiene. sguardo
Let l'esempio: s = "abcabcabc"
e la matrice è:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 1, 0, 0]
[0, 0, 2, 0, 0, 2, 0, 0, 2, 0]
[0, 0, 0, 3, 0, 0, 3, 0, 0, 3]
[0, 1, 0, 0, 4, 0, 0, 4, 0, 0]
[0, 0, 2, 0, 0, 5, 0, 0, 5, 0]
[0, 0, 0, 3, 0, 0, 6, 0, 0, 6]
[0, 1, 0, 0, 4, 0, 0, 7, 0, 0]
[0, 0, 2, 0, 0, 5, 0, 0, 8, 0]
[0, 0, 0, 3, 0, 0, 6, 0, 0, 9]
Nota le belle diagonali lì. Come vedi la prima diagonale finisce con 3, la seconda con 6 e la terza con 9 (la nostra soluzione DP originale che non ci interessa).
Questa non è una coincidenza. Spero che dopo aver esaminato maggiori dettagli su come viene costruita la matrice DP, puoi vedere che queste diagonali corrispondono a stringhe duplicate.
Ecco un esempio per s = "aaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtas"
e l'ultima riga della matrice è: [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 17, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 34, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 51, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 68]
.
Come si vedono i numeri grandi (17, 34, 51, 68) corrispondono alla fine delle diagonali (c'è anche un po 'di rumore solo perché ho aggiunto in particolare piccole lettere duplicate come aaa
).
Che suggeriscono che possiamo trovare lo gcd dei due numeri più grandi gcd(68, 51) = 17
che sarà la lunghezza della nostra sottostringa ripetuta.
Qui solo perché sappiamo che l'intera stringa consiste di sottostringhe ripetute, sappiamo che inizia nella posizione 0 ° (se non lo sappiamo dovremmo trovare l'offset).
E qui andiamo: la stringa è "aaabasdfwasfsdtas"
.
P.S. questo metodo consente di trovare le ripetizioni anche se sono leggermente modificate.
Per le persone che vorrebbero giocare qui intorno è uno script python (che è stato creato in un caos quindi sentitevi liberi di migliorare):
def longest_common_substring(s1, s2):
m = [[0] * (1 + len(s2)) for i in xrange(1 + len(s1))]
longest, x_longest = 0, 0
for x in xrange(1, 1 + len(s1)):
for y in xrange(1, 1 + len(s2)):
if s1[x - 1] == s2[y - 1]:
m[x][y] = m[x - 1][y - 1] + 1
if m[x][y] > longest:
longest = m[x][y]
else:
m[x][y] = 0
return m
s = "aaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtas"
m = longest_common_substring(s, s)
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
M = np.array(m)
print m[-1]
arr = np.asarray(M)
plt.imshow(arr, cmap = cm.Greys_r, interpolation='none')
plt.show()
ho parlato nel modo più semplice, e ho dimenticato di scrivere a proposito. Si sta facendo tardi, quindi spiegherò solo l'idea. L'implementazione è più difficile e non sono sicuro che vi darà risultati migliori. Ma eccolo:
Utilizzare l'algoritmo per longest repeated substring (sarà necessario implementare trie o suffix tree che non è facile in php).
Dopo questo:
s = "aaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtas"
s1 = largest_substring_algo1(s)
Ha preso l'attuazione di largest_substring_algo1 from here. In realtà non è il massimo (solo per mostrare l'idea) in quanto non utilizza le strutture dati sopra menzionate. I risultati per s
e s1
sono:
aaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtas
aaabasdfwasfsdtasaaabasdfwasfsdtasaaabasdfwasfsdtasaa
Come si vede la differenza tra loro è in realtà la stringa che è stato duplicato.
Correlati: http://venturebeat.com/2015/07/26/watch-this-brilliant-visualization-of-words-in-the-english-language/ –
non sto cercando di criticare l'approccio (lo so che funzionerà benissimo). Ma ecco un paio di domande: 1) come si troverà una frase duplicata (si tratta di n parole che abbiamo trovato, ma non ci sono n! Diverse possibilità). 2) cosa faresti se una persona scrivesse il testo senza spazi. –