2011-11-17 10 views
11

mam zadanie, które wymaga czytania ogromny plik przypadkowych wejść, na przykład:Jak osiągnąć "dopasowanie podłańcuchów" w czasie O (n)?

Adana 
Izmir Adnan Menderes Apt 
Addis Ababa 
Aden 
ADIYAMAN 
ALDAN 
Amman Marka Intl Airport 
Adak Island 
Adelaide Airport 
ANURADHAPURA 
Kodiak Apt 
DALLAS/ADDISON 
Ardabil 
ANDREWS AFB 
etc.. 

Gdybym podać szukaną frazę, program ma znaleźć linie którym wystąpi podciąg. Na przykład, jeśli wyszukiwanym hasłem jest "uradha", program ma pokazać ANURADHAPURA. Jeśli wyszukiwanym hasłem jest "lotnisko", program ma pokazać: Amman Marka Intl Airport, Adelaide Airport

Cytat ze specyfikacji przypisania: "Musisz zaprogramować tę aplikację, biorąc pod uwagę efektywność, tak jak w przypadku dużych ilości danych i przetwarzania. "

Mogę łatwo osiągnąć tę funkcję za pomocą pętli, ale wydajność będzie O (n). Myślałem o użyciu trie, ale wygląda na to, że działa tylko wtedy, gdy podciąg zaczyna się od indeksu 0.

Zastanawiam się, jakie są rozwiązania, które dają lepszą wydajność niż O (n)?

+0

Czy wszystkie linie są krótkie jak te pokazane? –

+0

@ MichaelJ.Barber. Zasadniczo wymagania są niejasne, mam tylko przykładowy plik: http://qweop.com/test/airports.dat – Pacerier

+1

nie potrzebujesz jak komputer kwantowy do przejrzenia listy N pozycji pod O (n)? –

Odpowiedz

10

Możesz rzucić okiem na Boyer-Moore string search algorithm lub Knuth-Morris-Pratt string search algorithm. Mają dobrą asymptotyczną wydajność, ale nie znam algorytmu, który nie wymagałby przynajmniej odczytu raz (prawie wszystkich) zarówno ciągu wejściowego, jak i wyjściowego, a zatem miałby lepszą wydajność niż O (n) (gdzie n jest wielkością danych wejściowych).

+0

W przypadku krótkich znanych podciągów, Rabin-Karp może również istnieć. – rossum

3

Mój gut mówi, że jesteś na dobrej myśli ścieżek trie a może chcesz, aby zbadać tę sekcję strony trie na Wikipedia że linki do Suffix Tree dla kilku innych pomysłów. O (n) pomysły niestety.

3

To tekst wejściowy zawartość niemal statyczne (lub wartości nie są dodawane tak często, a wartości są dodawane do końca źródła sygnału wejściowego), ale przeszukiwanie jest często można wypróbować następujące (prawdopodobnie taki sam jak trie)

1) będziesz przeczytać cały tekst (a także aktualizować następnie dodaje nowy element) i przygotować indeksy tabel (mapa symbolu współrzędnych (wiersz lub wiersz z pozycji) Jeśli występuje mecz)

'aa' - 1, 15, 27... 
'as' - 1, 15, 17... 
'ba' - 2, 3, 15... 
... 

2) Pierwsza współrzędna wyszukiwania w tabeli indeksów według pierwszych 2 symboli

3) Następnie kontynuuj wyszukiwanie w tekście wejściowym za pomocą współrzędnych

+0

Heys sry Nie rozumiem cię, czy nie oznaczałoby to, że potrzebowałbym mapy dla wszystkich możliwych wejść "a" do "zzzzzz" (która jest zbyt duża, aby mogła być realistycznie użyta?) – Pacerier

+1

Jest to znane jako [odwrócony indeks] (https://en.wikipedia.org/wiki/Inverted_index). Może być bardzo szybki, ponieważ indeks informuje o tym, jak skoncentrować wyszukiwanie. –

+0

@Pacerier: tak tabela indeksu będzie ogromna, nawet większa niż źródło wejściowe, ale zwiększy wydajność wyszukiwania. – Vitaliy

1

Boyer-Moore i kilka algorytmów, które wykorzystują warianty w niektórych swoich pomysłach, mogą osiągnąć "O (n/m)" (gdzie n jest długością stogu siana i m to długość igły) najlepsze działanie na niektórych igłach, ale zależy to od kryteriów braku powtórzenia na igle, których nie można spełnić dla arbitralnie dużych m (np. ponieważ m jest znacznie większy niż rozmiar zestawu znaków), czyniąc nawet najlepsze przypadki czymś bardziej podobnym do O (n/256), a zatem O (n). Wciąż w rzeczywistych aplikacjach, gdzie m jest zwykle mały, a igły nie mają patologicznego punktu widzenia, BM i jego kuzyni potrafią działać wyjątkowo dobrze.

Osobiście polecam algorytm "Dwukierunkowy" (z rozszerzeniami podobnymi do BM używanymi w implementacji glibc), ponieważ ma zagwarantowane granice O (n) i stałą przestrzeń roboczą.

Powiązane problemy