Egy ideje elakadtam, amely a leggyorsabb karakterlánc-keresési algoritmus, sok véleményt hallottam, de végül nem vagyok biztos benne.
Hallottam olyanokat, akik azt mondták, hogy a leggyorsabb algoritmus Boyer-Moore, és vannak, akik azt mondják, hogy Knuth-Morris-Pratt valójában gyorsabb.
Megkerestem mindkettőjük összetettségét de többnyire ugyanúgy néznek ki O(n+m)
. Megállapítottam, hogy a legrosszabb esetben Boyer-Moore O(nm)
komplexitással rendelkezik Knuth- Morris-Pratt, amelynek O értéke van (m + 2 * n). Ahol n = a szöveg és az m = a minta hossza.
Ha jól tudom, Boyer-Moore-nak lineáris-legrosszabb eset-ideje van ha a Galil-szabályt használnám.
Kérdésem, mindenekelőtt, ami valójában a leggyorsabb String keresési algoritmus (Ez a kérdés az összes lehetséges szúró algoritmust magában foglalja, nemcsak Boyer-Moore és Knuth-Morris-Pratt).
Szerkesztés: ez a válasz
Amit pontosan keresek:
Adott egy szöveg T
és egy mintát P
Meg kell találnom a P
összes megjelenését a T
-ban.
A P és T hossza szintén [1,2 000 000]
és a programnak 0,15 másodperc alatt kell futnia.
Tudom, hogy a KMP és Rabin-Karp elegendő ahhoz, hogy 100% -os pontszámot kapjon a problémáról, de én egyelőre ki akartam próbálni megvalósítani Boyer-Moore-t. Melyik lenne a legjobb az ilyen típusú mintakereséshez?
Megjegyzések
- Amikor ezeket tesztelte a választott nyelven, mit talált? / li>
- Egyes teszteken Boyer-Moore jobb volt a többi KMP-nél, de én ‘ nem vagyok biztos abban, hogy a ” legjobb ” megvalósításuk. Ami a választott nyelvet illeti, a következő címkékben található: C ++ (nem biztos, hogy látta ezt, mivel a ” választott nyelvet írta ” ). P.S. Abban sem vagyok biztos, hogy a legjobb teszteken teszteltem-e.
- stackoverflow.com/q/3183582
- Knuth-Morris-Pratt, amelynek O (m + 2 * n) … O-ra (m + n) gondol.
- Válasszon ki egy megfelelő algoritmikus bonyolultságot, majd mikro-hangolja a baromságokat egy profilozóval a kezében – nekem mindig bevált. 😀
Válasz
Ez a végrehajtandó keresés típusától függ. Mindegyik algoritmus különösen jól teljesít bizonyos típusú kereséseknél, de nem adta meg a keresések összefüggéseit.
Íme néhány tipikus gondolat a kereséstípusokról:
-
Boyer-Moore: a minta előzetes elemzésével és jobbról balra történő összehasonlítással működik. Ha eltérés következik be, akkor a kezdeti elemzés alapján meghatározzuk, hogy a minta mennyivel tolható el w.r.t. a keresett szöveg. Ez különösen jól működik hosszú keresési minták esetén. Különösen szub-lineáris lehet, mivel nem kell elolvasnia a szöveg minden egyes karakterét.
-
Knuth-Morris-Pratt: a mintát is előre elemzi , de megpróbálja újrafelhasználni azt, ami a minta kezdeti részében már megegyezett, hogy ne kelljen ezt újra megcsinálni. Ez nagyon jól működhet, ha az ábécé kicsi (pl. DNS-alapok), mivel nagyobb az esélye annak, hogy a keresési minták újrafelhasználható almintákat tartalmaznak.
-
Aho- Corasick: Sokat igényel előfeldolgozást, de számos mintához ezt teszi. Ha tudja, hogy ugyanazokat a keresési mintákat fogja keresni újra és újra, akkor ez sokkal jobb, mint a másiké, mert a mintákat csak egyszer kell elemeznie, keresésenként nem egyszer.
Ezért, mint a CS-ben szokás, nincs egyértelmű válasz az összességében legjobb ra. Inkább arról van szó, hogy a megfelelő eszközt válasszák ki a szóban forgó munkához.
Egy másik megjegyzés a legrosszabb esetről: Fontolja meg a legrosszabb eset létrehozásához szükséges keresések fajtáját, és alaposan gondolja át, hogy ezek valóban relevánsak az Ön esetében. Például a Boyer-Moore algoritmus legrosszabb esetének O(mn)
bonyolultsága egy keresési mintából és egy olyan szövegből fakad, amelyben mindegyik csak egy karaktert használ (például a >
itt:aaaaaaaaaaaaaaaaaaaaa
) – valóban gyorsnak kell lenned az ilyen keresésekhez?
Megjegyzések
- A teljes angol ábécét használhatom, és frissítettem a kérdést, sajnálom, hogy nem ezzel kezdtem a kolduláskor.
- És igen, gyorsnak kell lennem még olyan kereséseknél is, mint hogy
- kérem, fejtse ki a Z ‘ s algoritmust és a manachárt is?
Válasz
Bár kissé későn válaszolok erre a kérdésre, de azt hiszem, a Z-Algorithm
sokkal gyorsabb, mint bármelyik társa.Legrosszabb komplexitása O (m + n), és nem igényli a minta / szöveg előzetes feldolgozását. Ez a kódolás a többi algoritmushoz képest is nagyon egyszerű.
A következő módon működik.
Például létezik egy S ="abaaba"
karakterlánc. Meg kell találnunk a z(i)
értékeket a i=0 to len(S)-1
számára. Mielőtt belemennék a magyarázatba, hadd tegyek le néhány meghatározást.
z(i)
= nem. a S
előtag karaktereinek száma, amely megegyezik a s(i)
előtaggal.
s(i)
= ith
a S
utótag.
A következők a s(i)
s = "abaaba"
értékei.
s(0) = "abaaba" = S s(1) = "baaba" s(2) = "aaba" s(3) = "aba" s(4) = "ba" s(5) = "a"
A z értékek rendre
z(0) = 6 = length(S) z(1) = 0 z(2) = 1 z(3) = 3 z(4) = 0 z(5) = 1
Az algoritmus részletes megértéséhez lásd a következő hivatkozásokat.
http://codeforces.com/blog/entry/3107
https://www.youtube.com/watch?v=MFK0WYeVEag
Most O (N) kell, hogy megtalálja az összes z
értéket előzetes feldolgozás nélkül. Most arra lenne kíváncsi, hogyan lehet ezt a logikát felhasználni az adott karakterlánc mintájának összehangolásához?
Lássuk egy példával. Minta (P): aba
, Szöveg (T): aacbabcabaad
.
Tegye ezt P $ T formátumba. ($
– olyan karakter, amely nem jelenik meg sem mintában, sem szövegben. Rövid időn belül eljutok a $
fontosságához.)
P$T
= aba$aacbabcabaad
Tudjuk, hogy len(P)
= 3.
A P$T
összes z értéke
z(0) = 16 = len(P$T) z(1) = 0 z(2) = 1 z(3) = 0 z(4) = 1 z(5) = 1 z(6) = 0 z(7) = 0 z(8) = 2 z(9) = 0 z(10) = 0 z(11) = 3 z(12) = 0 z(13) = 1 Z(14) = 1 Z(15) = 0
Most melyik z(i)
= len(P)
. Ans = 11.
Tehát mintánk jelen van a Ans-len(P)-1
= 7
helyen. A -1
a $
karakterhez tartozik.
Most miért $
vagy minden ilyen különleges karakter fontos. Vegye figyelembe a P = "aaa"
és T = "aaaaaaa"
elemeket. A speciális karakter nélkül az összes z(i)
növekményes értékkel rendelkezik. Még mindig megtalálható a minta helyzete a szövegben az alábbi képletekkel:
Feltétel: z(i)
> = len(P)
és pozíció: Ans-len(P)
. De az állapot ebben az esetben kissé trükkös és zavaros lesz. Én személy szerint inkább a speciális karaktertechnikát használom.
Megjegyzések
- Magyaráznád itt magad? Külső webhelyekre mutató linkek felhasználhatók a kidolgozáshoz, de a válasz magjának inkább magában a válaszban kell lennie, nem pedig egy másik webhelyre mutató linket kell követnie.
- A z-algoritmus alapvetően megegyezik a kmp. Kétlem, hogy sokkal gyorsabb lenne.
- Egyetértek a @ThomasAhle céggel. A
z
kiszámítása előfeldolgozás . ‘ azért jó magyarázat. A válasz miattO(n)
módot állítottam fel a KMP előfeldolgozásról Z előfeldolgozásra való áttérésre. Itt
Válasz
Használja a tartalom címezhető memória , szoftveresen megvalósítva virtuális címzés formájában (betűk betűkre mutatva).
Ez egy átlagos karakterlánc-illesztési algoritmus számára felesleges.
A CAM egyidejűleg rengeteg mintát képes összeilleszteni, körülbelül 128 betűs mintázatig (ha ASCII, ha csak Unicode 64). Ez egy betűhosszonként egy hívás az egyeztetni kívánt karakterláncban, és egy véletlenszerű beolvasás a memóriából a maximális mintahossz hosszánként. Tehát, ha 100 000 betűs karakterláncot elemezne, akár 90 000 000 mintával egyidejűleg (ami körülbelül 128 GiB-re lenne szükség akkora minták számának tárolására), akkor 12 800 000 véletlenszerű olvasmányra lenne szükség a RAM-ból, tehát 1 ms alatt megtörténne. / p>
Így működik a virtuális címzés.
Ha 256 induló címmel kezdem, amelyek az első betűt jelentik, akkor ezek a betűk a következő betűk 256-ra mutatnak. Ha egy minta nem létezik, nem tárolja.
Tehát ha folyamatosan betűket kapcsolok a betűkhöz, akkor olyan, mintha 128 szelet virtuális címzés mutatna a virtuális címzésre.
Ez így lesz dolgozzon —, de hogy 900 000 000 mintát érjen el egyidejűleg, egy utolsó trükköt kell hozzáadni —, és kihasználja annak a ténynek, hogy sok újrakezdéssel kezdi ezeket a levélpuffereket, de később szétszóródik.Ha felsorolja a tartalmat, ahelyett, hogy kiosztaná mind a 256 karaktert, akkor ez nagyon lassan lassul, és “100-szoros kapacitásnövekedést kap, mert alapvetően csak 1 betűt használ minden levélmutató pufferben (amit én átneveztem” escape “).
Ha a legközelebbi szomszéd karakterlánc-egyezést akarod megszerezni, akkor ezek közül sok párhuzamosan fut, és hierarchiában gyűjtesz, így a hibát elfogulatlanul terjeszted. legközelebbi szomszéd csak egy, akkor elfogult vagy a fa kezdete felé.
Megjegyzések
- @MagnusRobertCarlWoot, ha ugyanaz van gavatar, mint a roucer81, vagy a hash-kód ütközésének csillagászati egybeesése, vagy ugyanaz az e-mail címe. Ha ugyanaz a személy áll mindkét fiók mögött, akkor a ” kapcsolatba léphet velünk ” űrlappal egyesítheti őket, hogy megfelelő hitelt kapjon a jó szavazatok révén megszerzett hírnév erre a válaszra.