2012-03-27 7 views
5

Mam duży zestaw adresów URL i chcę zaimplementować autouzupełnianie. Nie lubię złożoność naiwnego podejścia, jak to jest liniowy z wielkością zestawie:Jak utworzyć prosty indeks prefiksu w Javie?

for(String url: urls) if(url.startsWith(input) {doSomething();} 

Teraz wiem, że w Hash, funkcja „zawiera()” prace w „O (1) "ale nie ma" zawieraPrefix() ". Czy istnieje prosty sposób bez użycia dużej biblioteki, takiej jak Lucene, czy też samodzielnego kodowania? Nie miałbym problemu z tym, ale wydaje się, że jest to zbyt prosty problem, więc chcę wiedzieć, czy istnieje proste rozwiązanie :-)

Z moich zajęć informatycznych pamiętam drzewo, które składa się z fragmentów smyczków, ale Zapominam, jak to się nazywało. To działało tak:

[car, care, carrot,carrotville]-> 

car 
| 
-/ 
-e 
-rrot 
    | 
    ----ville 

P.S .: Jak wywołać metody, które zwracają wszystkie ciągi, których ciąg jest przedrostkiem? Podobnie jak w przypadku przedrostka b, jaki jest b do a?

+0

co chcesz zrobić? automatycznie dodajesz jakiś tekst na początku każdego ciągu? –

+0

Chcę wiedzieć, które ciągi znaków są przedrostkiem, więc mogę je podać jako podpowiedzi autouzupełniania. –

Odpowiedz

2

Jeśli chcesz skutecznie znaleźć prefiksy ciągów, użyj Trie, struktury danych przeznaczone właśnie do tego celu:

A trie lub drzewa prefiks, jest uporządkowana struktura danych drzewo, które służy do przechowuj tablicę asocjacyjną, w której klucze są zwykle ciągami. W przeciwieństwie do binarnego drzewa wyszukiwania żaden węzeł w drzewie nie przechowuje klucza skojarzonego z tym węzłem; zamiast tego jego pozycja w drzewie definiuje klucz, z którym jest skojarzony. Wszystkie potomkami węzła mają wspólny przedrostek łańcucha związanego z tym węźle, a korzeń jest związany z pustym ciągiem

dwa linki z sampleimplementations.

+1

Idealny! Użyłem tego z https://forums.oracle.com/forums/thread.jspa?messageID=8787521 i działało przy pierwszej próbie! –

1

Dawno temu kładę prostą implementację TRIE tutaj:

http://code.google.com/p/triebag/source/browse/trunk/src/triebag/tries/SimpleTrie.java

Jednak nie jest to kompaktowy Trie, dlatego tworzy jeden węzeł na znak, tworząc zwarty jeden jest nieco trudniejsze.

+0

To jest świetne! Nie mam nic przeciwko temu, czy jest to jeden węzeł na znak, ale pozostawię pytanie otwarte na wypadek, gdyby ktoś miał jedno z wielokrotnościami. –

+0

Np, wersja kompaktowa używa około 50 mniej węzłów (przynajmniej dla tureckich słów w słowniku) To jest kod testowy, więc możesz go zobaczyć w akcji, mam nadzieję, że nie ma błędów :) http://code.google.com/p/triebag/source/browse/trunk/test/triebag/tries/SimpleTrieTest.java – mdakin

+0

Wypróbowałem Twój SimpleTrie, ale nie działa to dla mnie. Najpierw konstruktor nie był publiczny i po jego zmianie następujący test nie zwrócił nic: 'SimpleTrie trie = new SimpleTrie <>(); \t \t trie.add ("x", "x"); \t \t trie.add ("xy", "xy"); \t \t Iterator it = trie.getItemsWithPrefix ("x"); \t podczas (it.hasNext()) System.out.println (it.next()); ' –

0

RegExp realizacja java.util.regex.Pattern mogą skutecznie obsługiwać przedrostki:

StringBuilder buffer = new StringBuilder(); 
for (String prefix : prefixes) { 
    if (buffer.length() > 0) 
     buffer.append("|"); 
    buffer.append(prefix); 
} 
Pattern prefixPattern = Pattern.compile("^(" + buffer + ")"); 

można przetestować wszystkie przedrostki:

boolean containsPrefix = prefixPattern.matcher(stringToTest).find(); 

Uwaga: dla uproszczenia ciągi prefiksów nie są chronione. Znaki Regexp [,], \, *,?, $, ^, (,), {,} I | musi być poprzedzony przez \.