L'algorithme de la plus longue sous-séquence commune n'exige pas que les correspondances soient des sous-chaînes contiguës. Par exemple, pour les chaînes "computer" et "houseboat" la sous-séquence est "out". c'est ce que tu veux?
Si vous voulez que les correspondances soient des sous-chaînes contiguës, cela s'appelle longest repeated substring problem. Le lien décrit un algorithme de temps et d'espace linéaire utilisant des arbres de suffixes.
Si vous voulez quelque chose de court et simple, voici une approche basée sur l'algorithme LCS, mais sans table. L'idée est de boucler tous les décalages d'entiers possibles entre la sous-chaîne désirée et sa duplication. Pour chaque décalage, recherchez la plus grande correspondance contiguë en analysant la chaîne une fois. Si la chaîne d'entrée a une longueur n, il y a O (n) décalages possibles et la vérification de chaque décalage prend O (n), donc le coût total est O (n^2), avec seulement une quantité constante d'espace. (Comparez à ma réponse de dictionnaire simple qui prend l'espace O (n^3) et l'espace O (n^2).) Si vous ne voulez pas de chevauchement des correspondances (ie vous voulez que "bbbb" retourne "bb" pas "bbb"), puis en vérifiant chaque changement, vous vous arrêtez si le plus grand match dépasse le quart de travail. Voici le code C#:
public static string FindDuplicateSubstring(string s,
bool allowOverlap = false)
{
int matchPos = 0, maxLength = 0;
for (int shift = 1; shift < s.Length; shift++) {
int matchCount = 0;
for (int i = 0; i < s.Length - shift; i++) {
if (s[i] == s[i+shift]) {
matchCount++;
if (matchCount > maxLength) {
maxLength = matchCount;
matchPos = i-matchCount+1;
}
if (!allowOverlap && (matchCount == shift)) {
// we have found the largest allowable match
// for this shift.
break;
}
} else matchCount = 0;
}
}
if (maxLength > 0) return s.Substring(matchPos, maxLength);
else return null;
}
Je l'ai testé ce contre ma réponse dictionnaire et donne les mêmes résultats. Mais pour une chaîne aléatoire de longueur 3000, le dictionnaire prend 15 secondes, alors que la méthode ci-dessus prend 60ms (et beaucoup moins de mémoire).
Avez-vous besoin de seulement "mot entier" recherche? Dans ce cas, il suffit de diviser le texte en mots et d'utiliser la liste ou le dictionnaire .. –