6
votes

La plus longue sous-chaîne non chevaucheuse

Je me demande si quelqu'un connaît l'algorithme (optimal?) pour une sous-chaîne de sous-chevaucheuse récurrente la plus longue.

Par exemple, dans la chaîne

abadzedgbadez

Le plus long récurrent serait "mauvais". Incidemment, s'il n'y a pas de tel résultat, l'algorithme devrait alerter qu'une telle chose s'est produite. Je suppose que cela implique suffixe des arbres.

Je suis sûr que cela doit exister déjà quelque part. Merci pour l'aide!


2 commentaires

Juste curieux - Quelle est la demande d'entreprise pour cela?


Ce n'est pas une application commerciale. Il est lié à la recherche du thème dans une chanson et est plus un curio pour le moment jusqu'à ce que je reçoive un projet impliquant cela. =]


4 Réponses :


4
votes

Puisque vous l'appliquez sur la musique, vous ne recherchez probablement pas de matchs à 100%; Il y aura attendu des divergences d'une instance du thème à un autre. Vous pouvez essayer d'utiliser des algorithmes d'analyse de séquence de gènes - il y a beaucoup de cette variété de choses qui y vont. Essayez de souffler ou d'autres algorithmes d'alignement.

Vous pouvez également essayer la famille des algorithmes WinerpiPi, ainsi que diverses implémentations de préfixes de cet ensemble de résultats spécifique (ces résultats permettent des lacunes dans la sous-chaîne; par exemple, ABCID et AFBCD contiennent tous deux ABCD). En fait, j'ai un papier sur un algorithme qui pourrait être intéressant si vous seriez intéressé; J'aurais besoin d'atteindre l'autorisation de distribution, alors faites le moi savoir.

Notez que c'est en fait un sujet très compliqué (à faire efficacement) pour de grands ensembles de données.

Source: recherche depuis un an ou deux sur un sujet comparable (détection à thème).


7 commentaires

Si vous pouviez me donner accès, cela serait apprécié!


Je pense qu'il applique ceci aux paroles, alors je pense qu'il recherche 100% des matchs.


@Brandon - J'ai demandé la permission, je vais voir ce que je peux faire. @ las3rjock - pas vraiment. Par exemple: j'étais un homme idiot que j'étais stupide, exemple de l'homme à thème: la bombe passée. Les chaînes ne sont pas une correspondance exacte. De plus, beaucoup de paroles ont une ponctuation différente et ce que rien. Donc, je ne suis pas sûr qu'il recherche une correspondance exacte.


BAH Mise en forme. Exemple était "J'étais un homme idiot" Versus "J'étais stupide, homme"


@Brandon - s'avère qu'il n'y a pas de clauses de distribution, donc je posterai un lien ce soir :)


Ouais, à propos de la chose des paroles. Je parle de classifier littéralement la musique par des notes. Cela n'a rien à voir avec les paroles. Vous pouvez transcoder des notes musicales dans une chaîne de symboles. Merci d'avoir vérifié les droits de distribution! =]


Vous allez - lamegame.no-ip.org/public/prefixtrees_wwwkwdistributable.pdf > Notez que la section Algorithmes est la section 4 et le pseudo-code il est assez explicite. Sentez-vous absolument libre de poser des questions supplémentaires sur le contenu ou la manière dont vous pourriez la modifier pour fonctionner mieux. Tout comme une tête en tête, vous opériez avec une survenue d'un mot comme une "fonctionnalité" probablement, et pour votre composant "Time", utilisez simplement des entiers qui indiquent la position dans la phrase. Espérons que cela a du sens après avoir regardé le papier.




1
votes

Un simple algorithme est de le faire:

  • Créez une structure de données représentant des tranches d'une chaîne; Mettre en œuvre la comparaison / le tri, le cas échéant pour la langue
  • Créez une liste de chaque tranche de la chaîne en commençant par [Premier caractère, dernier caractère], [Personnel secondaire, dernier caractère], jusqu'à [le dernier caractère, dernier caractère]
  • Trier cette liste - O (N LOGN N)
  • Ceci apporte toutes les tranches de chaîne avec des préfixes courants ensemble. Vous pouvez ensuite itérer via la liste, en comparant chaque paire pour voir combien de caractères ils partagent au début et, s'il est plus grand que votre maximum, prenez-en une note et définissez-le comme le nouveau maximum

    (comme l'autre réponse vient de poster indique, je décris un ensemble de suffixe ici.)


2 commentaires

Ceci est encore plutôt brutal. Je me demande s'il y a une approche légèrement plus élégante? Je crois qu'une approche arborée préserverait les informations structurelles et fournirait une sorte d'informations de profondeur pouvant être rapidement traversée pour fournir des informations de longueur les plus longues.


Avec un type approprié - voir l'article du suffixe Wikipedia - L'heure de fonctionnement est O (n journalisation) dans le pire des cas et généralement mieux. L'itération est O (n), il est donc dominé par le tri des coûts de tri. La force brute évidente sera du moins (n ​​^ 2) au moins (comparant chaque paire possible). Les arbres de construction vont probablement coûter beaucoup plus de mémoire, ce qui aura des effets néfastes réels sur la performance (considérer le cache, etc.).



0
votes

D'accord, voici une idée folle.

Créer une fonction qui détermine s'il existe une sous-chaîne récurrente de la longueur K dans O (n) (où N est la longueur du texte). Cela peut être fait en utilisant un hachage roulant (voir Wikipedia pour RABIN-KARP STRING ALGORITHM A >) Pour générer tous les n hachages en temps linéaire et utiliser une hache / BST (ou une carte ou une carte dict ou quelle que soit votre langue l'appelle) pour stocker les positions de sous-chaînes correspondantes. Avant d'insérer le hachage actuel à la structure de données, nous vérifions si nous l'avons déjà vu auparavant. Si cela a été vu auparavant, nous recherchons simplement les indices où ce hachage a été généré et voyez si la sous-chaîne correspondante est une correspondance non chevauchante. P>

Maintenant que nous pouvons trouver une sous-chaîne de la duque à O (n ) Temps, nous exécutons simplement une recherche binaire pour trouver le plus grand K pour lequel nous pouvons trouver une correspondance de substration non chevauchante à l'aide de notre fonction. P>

code dans Python suit P>

A=23
MOD=10007 # use a random value in the real world

def hsh(text):
    return sum([ord(c)*A**(len(text)-i-1) for i,c in enumerate(text)])%MOD

def k_substring(text, k):
    substrings={}
    cur=hsh(text[:k])
    pwr=(A**(k-1))%MOD
    substrings[cur]=[0]
    for i in xrange(k,len(text)):
        to_remove=(ord(text[i-k])*pwr)%MOD
        to_add=ord(text[i])
        cur-=to_remove
        if cur<0:
            cur+=MOD
        cur=(cur*A)%MOD
        cur=(cur+to_add)%MOD
        if cur in substrings:
            lst=substrings[cur]
            for index in lst:
                if index+k<=i-k+1 and text[index:index+k]==text[i-k+1:i+1]:
                    return index
            lst.append(i-k+1)
        else:
            substrings[cur]=[i-k+1]
    return -1

def longest_substring(text):
    hi,lo=len(text),0
    while hi>lo:
        mid=(hi+lo+1)>>1
        if k_substring(text,mid)==-1:
            hi=mid-1
        else:
            lo=mid
    index=k_substring(text,lo)
    return text[index:index+lo]


0 commentaires