Самая длинная неперекрывающаяся подстрока

Последним руководством является "идентификатор", для больше на этом и других (например, "Хорошо"), см. мое сообщение на очень последнем Руководстве по проектированию Платформы (2-й выпуск)

5
задан Michal Sznajder 19 May 2010 в 20:46
поделиться

4 ответа

Since you're applying this to music, you're probably not looking for 100% matches; there will be expected discrepencies from one instance of the theme to another. You might try looking up gene sequence analysis algorithms - there's lots of this variety of stuff going on there. Try BLAST or other alignment algorithms.

You could also try the WinEPI family of algorithms, as well as various prefix tree implementations of this specific result set (these results allow gaps in the substring; for instance, ABCID and AFBCD both contain ABCD). I actually have a paper on an algorithm that might be worth looking at if you would be interested; I would need to attain distribution authorization, so let me know.

Note that this is actually a VERY complicated subject (to do efficiently) for large datasets.

Source: Research for a year or two on a comparable (theme-detection) topic.

4
ответ дан 14 December 2019 в 01:12
поделиться

Массив суффиксов - хорошая структура данных для решения этой проблемы.

Решение этой проблемы можно найти в Programming Pearls Джона Бентли.

]
4
ответ дан 14 December 2019 в 01:12
поделиться

Вот простой алгоритм:

  • Создайте структуру данных, представляющую срезы строки; реализовать сравнение / сортировку в соответствии с языком
  • Создайте список каждого фрагмента строки, начиная с [first-character, last-character], [second-character, last-character], до [last-character, последний символ]
  • Сортировка этого списка - O (n log n)
  • Это объединяет все фрагменты строки с общими префиксами. Затем вы можете перебирать список, сравнивая каждую пару, чтобы увидеть, сколько символов они разделяют в начале, и если оно больше вашего максимума, запишите его и установите как новый максимум

(как другой ответ только что опубликованный указывает, что здесь я описываю массив суффиксов.)

1
ответ дан 14 December 2019 в 01:12
поделиться

Хорошо, вот одна безумная идея .

Создайте функцию, которая определяет, есть ли повторяющаяся подстрока длины k в O (n) (где n - длина текста). Это можно сделать с помощью скользящего хеша (см. Википедию для Алгоритм сопоставления строк Рабина-Карпа ) для генерации всех n хэшей за линейное время и с помощью хеш-таблицы / BST (или карты, или словаря, или любого другого языка вызывает его) для хранения соответствующих позиций подстроки. Перед тем, как вставить текущий хеш в структуру данных, мы проверяем, видели ли мы его раньше. Если это уже было замечено ранее, мы просто ищем индексы, по которым был сгенерирован этот хэш, и проверяем, является ли соответствующая подстрока неперекрывающимся совпадением.

Теперь, когда мы можем найти подстроку длины k за время O (n), мы просто запустите двоичный поиск, чтобы найти наибольшее k, для которого мы можем найти совпадение неперекрывающейся подстроки с помощью нашей функции.

Код в Python следует за

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]

(Извините, если это неясно. Сейчас 6:30 утра, и я действительно нужно лечь спать :))

Перед тем, как вставить текущий хеш в структуру данных, мы проверяем, видели ли мы его раньше. Если это уже было замечено ранее, мы просто ищем индексы, по которым был сгенерирован этот хэш, и проверяем, является ли соответствующая подстрока неперекрывающимся совпадением.

Теперь, когда мы можем найти подстроку длины k за O (n) время, мы просто запустите двоичный поиск, чтобы найти наибольшее k, для которого мы можем найти совпадение неперекрывающейся подстроки с помощью нашей функции.

Код в Python следует за

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]

(Извините, если это неясно. Сейчас 6:30 утра, и я действительно нужно лечь спать :))

Перед тем, как вставить текущий хеш в структуру данных, мы проверяем, видели ли мы его раньше. Если это уже было замечено ранее, мы просто ищем индексы, по которым был сгенерирован этот хэш, и проверяем, является ли соответствующая подстрока неперекрывающимся совпадением.

Теперь, когда мы можем найти подстроку длины k за O (n) время, мы просто запустите двоичный поиск, чтобы найти наибольшее k, для которого мы можем найти совпадение неперекрывающейся подстроки с помощью нашей функции.

Код в Python следует за

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]

(Извините, если это неясно. Сейчас 6:30 утра, и я действительно нужно лечь спать :))

0
ответ дан 14 December 2019 в 01:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: