Pierwsze int reprezentację String

głosy
5

Szukam sposobu na stworzenie int \ długą reprezentację dowolnej alfanumerycznego String. Kody Hash nie zrobi, bo nie może sobie pozwolić na kolizje mieszania czyli reprezentacja musi być unikalny i powtarzalne.

Wartość liczbowa zostanie wykorzystana do wydajnego (oby) porównuje. Stworzenie klucza numerycznego zajmie trochę czasu, ale to ma się wydarzyć tylko raz, podczas gdy trzeba wykonać ogromną liczbę porównań z nim - co mam nadzieję być znacznie szybsze niż porównywanie surowe ciągi.

Inny pomysł na temat szybszego porównaniu String będą najbardziej cenione zbyt ...

Utwórz 05/09/2008 o 17:11
źródło użytkownik
W innych językach...                            


14 odpowiedzi

głosy
12

Chyba, że ​​łańcuch ma ograniczoną długość, nie można uniknąć kolizji.

Istnieje 4294967296 możliwych wartości dla liczby całkowitej (2 ^ 32). Jeśli masz więcej niż ciąg 4 znaków ASCII, lub więcej niż dwóch znaków Unicode, to istnieje więcej możliwych wartości ciągów niż możliwych wartości całkowitych. Nie można mieć unikalną wartość całkowitą dla każdego możliwego ciągiem 5 znaków. Długie wartości mają więcej możliwych wartości, ale stanowią one tylko unikalną wartość dla każdego możliwego ciąg 8 znaków ASCII.

Hash kody są użyteczne jako proces dwuetapowy: najpierw sprawdzić, czy kod hash zapałki, a następnie sprawdzić cały łańcuch. Dla większości strun, które nie pasują, trzeba tylko zrobić pierwszy krok, i to bardzo szybko.

Odpowiedział 05/09/2008 o 17:23
źródło użytkownik

głosy
10

Nie można po prostu zacząć z kodem hash, a jeśli mecz kody hash, zrobić znak porównania znaków?

Odpowiedział 05/09/2008 o 17:15
źródło użytkownik

głosy
5

Jak długo są struny? Jeśli są bardzo krótkie, a unikalny identyfikator może być generowane za znaki cyframi w podstawie 36 (26 + 10), które tworzą n -digits liczbę gdzie n jest długością łańcucha. Z drugiej strony, jeśli struny są wystarczająco krótki, aby umożliwić tym bezpośrednie porównanie nie będzie problemem w każdym razie.

W przeciwnym razie będziesz musiał wygenerować bezkolizyjny hash i można to zrobić tylko wtedy, gdy pełna przestrzeń problem jest znany z góry (czyli jeśli znasz wszystkie ciągi, które mogą ewentualnie wystąpić). Będziemy chcieli, aby rzucić okiem na doskonałej mieszaja , chociaż tylko algorytm możliwe, aby znaleźć idealne funkcji skrótu, że wiem, jest probabilistyczny tak kolizje są jeszcze teoretycznie możliwe.

Mogą istnieć inne sposoby, aby znaleźć taką funkcję. Knuth nazywa to „raczej zabawny ... puzzle” w TAoCP ale on nie daje algorytm albo.

W ogóle, dajesz zbyt kilka informacji, aby znaleźć algorytm, który nie wymaga sondowania całą przestrzeń problem w jakiś sposób. To nie zawsze oznacza to, że problem ma wykładniczy czas pracy, ale może być rozwiązany za pomocą heurystyki machine-learning. Nie jestem pewien, czy to jest wskazane w danym przypadku.

Odpowiedział 05/09/2008 o 17:20
źródło użytkownik

głosy
2

Pod koniec dnia, jeden znak alfanumeryczny ma co najmniej 36 możliwych wartości. Jeśli zawierają znaki interpunkcyjne, małe litery, etc następnie można łatwo przejść 72 możliwych wartości.

Szereg innych niż kolizji, które pozwala szybko porównać ciągi nieuchronnie rośnie wykładniczo wraz z długością łańcucha.

Więc najpierw musi zdecydować, na najdłuższym ciągiem spodziewasz porównać. Zakładając, że to N znaków długości, a zakładając, trzeba tylko wielkie litery i cyfry 0-9 wtedy gdy trzeba mieć reprezentację całkowitą, która może być tak wysokie, jak 36 ^ n

Dla łańcucha o długości 25 (nazwa wspólnego pola), a następnie skończyć się konieczności liczbę binarną ze 130 bitów.

Jeśli komponować, że na 32-bitowych liczb, musisz 4. Następnie można porównać każdy numer (cztery całkowitą porównuje powinny podjąć czasu, w porównaniu do chodzenia ciąg). Polecam duża liczba bibliotekę, ale w tym przypadku specjalistycznego Jestem całkiem pewien, że można napisać własny i uzyskać lepszą wydajność.

Jeśli chcesz obsługiwać 72 możliwych wartości na znaku (wielkie litery, małe litery, cyfry, znaki interpunkcyjne ...) i trzeba 10 znaków, to musisz 62 bitów - dwa 32-bitowe liczby całkowite (lub jeden 64-bitowy, jeśli jesteś na system, który obsługuje 64 bitowego)

Jeżeli jednak nie jesteś w stanie ograniczyć liczby w ciągu (czyli może być każdy z 256 litery / cyfry / znaki / etc) i nie można określić rozmiar napisu, a następnie porównanie ciągów jest bezpośrednio jedyna droga, ale jest to skrót.

Odlewanie wskaźnik w ciągu do 32-bitowe liczby całkowitej bez znaku tablicy, i porównywanie ciągów 4 bajty w czasie (lub 64 bitów / 8bytes na raz na 64-bitowy procesor). Oznacza to, że ciąg 100 znaków wymaga tylko 25 porównuje maksymalnie do znalezienia, która jest większa.

Być może trzeba ponownie zdefiniować zestaw znaków (i konwertować ciągi) tak, że postacie z wyższym priorytecie są przypisane wartości bliższa 0, a niższe wartości pierwszeństwa bliżej do 255 (lub odwrotnie, w zależności od sposobu ich porównanie) ,

Powodzenia!

-Adam

Odpowiedział 05/09/2008 o 17:36
źródło użytkownik

głosy
1

Tak długo, jak jest to funkcja skrótu, czy to String.hashCode (), MD5 lub SHA1, kolizja jest nieunikniona, chyba że masz stały limit długości struny. Jest to matematycznie niemożliwe, aby mieć jeden do jednego mapowania z nieskończonej grupy do skończonej grupy.

Cofając się, jest unikanie kolizji absolutnie konieczne?

Odpowiedział 05/09/2008 o 23:25
źródło użytkownik

głosy
1

Kilka pytań na początek:

  1. Czy przetestować że proste porównanie ciąg jest zbyt niska?
  2. Jak wygląda porównanie (== 'abc' 'abc' lub 'ABC'! = 'Abc')?
  3. Ile masz ciąg do porównania?
  4. Ile porównanie masz robić?
  5. Jak struny wyglądać (długość, wielkość liter)?

O ile pamiętam String w Javie jest obiektem i dwa identyczne ciągi wskazują na ten sam obiekt.

Więc może to byłoby na tyle, aby porównać przedmiotów (prawdopodobnie porównanie łańcuch jest już realizowany w ten sposób).

Jeśli to nie pomoże, można spróbować użyć realizację Pascal obiektu strun przy pierwszym elementem jest długość i jeśli struny mają różne długości powinno to zaoszczędzić trochę czasu procesora.

Odpowiedział 05/09/2008 o 17:22
źródło użytkownik

głosy
1

Być może:

String y = "oiu291981u39u192u3198u389u28u389u";
BigInteger bi = new BigInteger(y, 36);
System.out.println(bi);
Odpowiedział 05/09/2008 o 17:21
źródło użytkownik

głosy
1

Dlaczego nie można zrobić coś takiego 1stChar + (10 x 2ndChar) + (100 x 3rdChar) ...., gdzie można wykorzystać prosty wartość całkowitą każdego znaku, czyli a = 1, b = 2 itd, lub po prostu całkowitą wartość, jeśli nie jest to list. To daje unikalną wartość dla każdej struny, nawet dla 2 ciągi, które są takie same litery w innej kolejności.

Oczywiście, jeśli staje się bardziej skomplikowana, jeśli trzeba się martwić o Unicode, a nie tylko ASCII i numery można uzyskać duży, jeśli trzeba użyć długiego łańcucha.

Są to standardowe funkcje porównania ciąg Java na pewno nie na tyle wydajny?

Odpowiedział 05/09/2008 o 17:20
źródło użytkownik

głosy
0

Długość łańcucha może się zmieniać, ale powiedzmy 10 znaków do teraz.

W takim przypadku, w celu zapewnienia unikalności trzeba by użyć jakiegoś wielkiego reprezentacji całkowitej. Wątpię, że robi porównań na dużych liczb byłoby znacznie szybciej niż robi porównań ciągów w pierwszej kolejności. Zaraz sekundy jakie nawzajem mówili tu użyć jakiegoś hash, a następnie w przypadku meczu hash sprawdź oryginalne struny pozbyć się wszelkich kolizji.

W każdym razie, jeśli struny są około 10 znaków, wątpię, że porównywanie, powiedzmy, pęczek 32 bitowych mieszań będzie aż tak dużo szybciej niż bezpośrednich porównań łańcuchowych. Myślę, że trzeba zadać sobie pytanie, czy to naprawdę warto dodatkową złożoność.

Odpowiedział 05/09/2008 o 17:24
źródło użytkownik

głosy
0

Wydawać by się mogło, że MD5 hash będzie działać prawidłowo. Ryzyko kolizji hash byłoby niezwykle mało prawdopodobne. W zależności od długości łańcucha, który generuje hash int / długo napotkasz problemy maksymalnej wartości bardzo szybko.

Odpowiedział 05/09/2008 o 17:19
źródło użytkownik

głosy
0

Zakładając „alfanumeryczne” oznaczają litery i cyfry, można traktować każdą literę / cyfrę jako base-36 cyfry. Niestety, duże ciągi spowoduje, że liczba szybko rośnie i trzeba było uciekać się do wielkich liczb, które są mało wydajne.

Jeśli twoje łańcuchy są zazwyczaj różni podczas dokonywania porównań (czyli poszukiwanie konkretnego napisu) hash może być najlepszym rozwiązaniem. Gdy pojawi się potencjalny przebój, można zrobić porównanie ciąg aby się upewnić. Dobrze zaprojektowany hash uczyni kolizje niezmiernie rzadkie.

Odpowiedział 05/09/2008 o 17:18
źródło użytkownik

głosy
0

Jeśli nie chcesz, kolizje, spróbować czegoś szalony jak SHA-512. Nie mogę zagwarantować, że nie będzie kolizji, ale nie sądzę, że znaleźli każdy jeszcze.

Odpowiedział 05/09/2008 o 17:16
źródło użytkownik

głosy
0

Jak duże są twoje sznurki? Dowolnie długie łańcuchy nie mogą być skompresowane w formacie 32/64 bit.

Odpowiedział 05/09/2008 o 17:15
źródło użytkownik

głosy
0

Jak długo są struny? Jeśli nie wybierzesz int reprezentacji, który jest dłuższy niż ciąg, kolizje zawsze będzie możliwe, bez względu na to konwersja używasz. Więc jeśli używasz 32 bitową liczbę całkowitą, można tylko wyjątkowo reprezentować ciągi o długości do 4 bajtów.

Odpowiedział 05/09/2008 o 17:14
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more