Zoek naar een subtekenreeks in de tekst (tekenreeks). Brute force-algoritme

Brute Force-methode

Volledige zoekopdracht(of brute force-methode uit het Engels brute kracht) - een methode om een ​​probleem op te lossen door alle mogelijke opties te doorzoeken. De complexiteit van een volledige zoektocht hangt af van de dimensie van de ruimte van alle mogelijke oplossingen voor het probleem. Als de oplossingsruimte erg groot is, kan uitputtend zoeken mogelijk pas enkele jaren of zelfs eeuwen lang geen resultaten opleveren.

Kijk wat de “Brute Force-methode” is in andere woordenboeken:

    Compleet zoeken (of de ‘brute force’-methode uit het Engelse brute force) is een methode om een ​​probleem op te lossen door alle mogelijke opties te doorzoeken. De complexiteit van een volledige zoektocht hangt af van de dimensie van de ruimte van alle mogelijke oplossingen voor het probleem. Als de oplossingsruimte... ... Wikipedia

    Sorteren op basis van eenvoudige uitwisselingen, bubble sort is een eenvoudig sorteeralgoritme. Dit algoritme is het eenvoudigst te begrijpen en te implementeren, maar is alleen effectief voor kleine arrays. Complexiteit van het algoritme: O(n²). Algoritme... ... Wikipedia

    Deze term heeft andere betekenissen, zie Overkill. Brute kracht (of brute kracht) is een methode voor het oplossen van wiskundige problemen. Behoort tot de klasse van methoden om een ​​oplossing te vinden door alle mogelijke... ... Wikipedia uit te putten

    De omslag van de eerste editie van de brochure "Bail's Papers..." De cryptogrammen van Bale zijn, zoals verwacht, drie gecodeerde berichten die informatie bevatten over de locatie van een schat aan goud, zilver en edelstenen, naar verluidt begraven in het gebied ... Wikipedia

    Snefru is een cryptografische eenrichtingshashfunctie voorgesteld door Ralph Merkle. (De naam Snefru zelf, die de tradities voortzet van de blokcijfers Khufu en Khafre, ook ontwikkeld door Ralph Merkle, is de naam van de Egyptische ... ... Wikipedia

    Een poging om gegevens te kraken (decoderen) die zijn gecodeerd met een blokcode. Alle belangrijke soorten aanvallen zijn van toepassing op blokcijfers, maar er zijn enkele aanvallen die alleen specifiek zijn op blokcijfers. Inhoud 1 Soorten aanvallen 1.1 Algemeen ... Wikipedia

    Neurocryptografie is een tak van cryptografie die het gebruik van stochastische algoritmen, in het bijzonder neurale netwerken, voor codering en cryptanalyse bestudeert. Inhoud 1 Definitie 2 Toepassing ... Wikipedia

    De optimale route voor een handelsreiziger door de 15 grootste steden van Duitsland. De aangegeven route is de kortste van alle mogelijke 43.589.145.600

    Cryptografische hashfunctie Naam N Hash Gemaakt in 1990 Gepubliceerd in 1990 Hashgrootte 128 bits Aantal rondes 12 of 15 Type hashfunctie N Hash cryptografische ... Wikipedia

    Het handelsreizigersprobleem (traveling salesman) is een van de bekendste combinatorische optimalisatieproblemen. De taak is om de meest winstgevende route te vinden die minstens één keer per... ... Wikipedia door de opgegeven steden gaat


De brute force-methode is een directe benadering van het oplossen

van een probleem, meestal rechtstreeks gebaseerd op de probleemstelling en definities van de gebruikte concepten.

Een brute force-algoritme voor het oplossen van een algemeen zoekprobleem wordt sequentieel zoeken genoemd. Dit algoritme vergelijkt eenvoudigweg de elementen van een bepaalde lijst één voor één met de zoeksleutel totdat een element met de opgegeven sleutelwaarde wordt gevonden (succesvolle zoekopdracht) of de hele lijst wordt gecontroleerd, maar het gewenste element niet wordt gevonden (mislukte zoekopdracht). Er wordt vaak een eenvoudige extra truc gebruikt: als u de zoeksleutel aan het einde van de lijst toevoegt, zal de zoekopdracht zeker succesvol zijn. Daarom kunt u de controle op voltooiing van de lijst in elke iteratie van het algoritme verwijderen. Het volgende is de pseudocode voor zo'n verbeterde versie; Er wordt aangenomen dat de invoergegevens de vorm hebben van een array.

Als de oorspronkelijke lijst gesorteerd is, kun je profiteren van nog een verbetering: het zoeken in zo'n lijst kan worden gestopt zodra een element wordt aangetroffen dat niet kleiner is dan de zoeksleutel. Sequentieel zoeken vormt een uitstekende illustratie van de brute force-methode, met zijn karakteristieke sterke punten (eenvoud) en zwakke punten (lage efficiëntie).

Het is overduidelijk dat de looptijd van dit algoritme binnen zeer ruime grenzen kan variëren voor dezelfde lijst met grootte n. wanneer de lijst het gewenste element niet bevat, of wanneer het gewenste element zich als laatste in de lijst bevindt, zal het algoritme het grootste aantal bewerkingen uitvoeren door de sleutel te vergelijken met alle n elementen van de lijst: C(n) = n.

1.2. Rabins algoritme.

Het algoritme van Rabin is een wijziging van het lineaire algoritme en is gebaseerd op een heel eenvoudig idee:

“Laten we ons voorstellen dat we in een woord A, waarvan de lengte m is, zoeken naar een patroon X met lengte n. Laten we een "venster" met grootte n uitknippen en dit langs het invoerwoord verplaatsen. We zijn geïnteresseerd of het woord in het “vakje” overeenkomt met het gegeven patroon. Het vergelijken van letters duurt lang. In plaats daarvan fixeren we een numerieke functie op woorden met lengte n, waarna het probleem wordt beperkt tot het vergelijken van getallen, wat ongetwijfeld sneller is. Als de betekenissen van deze functie op het woord in de "box" en op het monster verschillend zijn, dan is er geen toeval. Alleen als de waarden hetzelfde zijn, is het nodig om de match letter voor letter opeenvolgend te controleren.”

Dit algoritme voert een lineaire verplaatsing over een lijn uit (n stappen) en een lineaire verplaatsing over de gehele tekst (m stappen), dus de totale looptijd is O(n+m). Tegelijkertijd houden we geen rekening met de tijdscomplexiteit van het berekenen van de hashfunctie, aangezien de essentie van het algoritme is dat deze functie zo eenvoudig te berekenen moet zijn dat de werking ervan de algehele werking van het algoritme niet beïnvloedt.

Het algoritme van Rabin en het sequentiële zoekalgoritme zijn de minst arbeidsintensieve algoritmen en zijn dus geschikt voor gebruik bij het oplossen van een bepaalde klasse van problemen. Deze algoritmen zijn echter niet de meest optimale.

1.3. Knuth-Morris-Pratt (kmp)-algoritme.

De KMP-methode maakt gebruik van voorverwerking van de zoekreeks, namelijk: op basis daarvan wordt een prefixfunctie gemaakt. Er wordt gebruik gemaakt van het volgende idee: als het voorvoegsel (ook wel achtervoegsel) van een string met lengte i langer is dan één teken, dan is het ook het voorvoegsel van een substring met lengte i-1. We controleren dus het voorvoegsel van de vorige subtekenreeks, als dit niet overeenkomt, dan het voorvoegsel van het voorvoegsel ervan, enz. Door dit te doen, vinden we het grootste vereiste voorvoegsel. De volgende vraag die het beantwoorden waard is, is: waarom is de looptijd van de procedure lineair, aangezien deze een geneste lus bevat? Ten eerste vindt de toewijzing van de prefixfunctie precies m keer plaats, de rest van de tijd verandert de variabele k. Daarom is de totale looptijd van het programma O(n+m), d.w.z. lineaire tijd.

en de volgende functie: function show(pos, path, w, h) ( var canvas = document.getElementById("canID"); // haal het canvasobject op var ctx = canvas.getContext("2d"); // it heeft eigenschap - tekencontext var x0 = 10, y0 = 10; // positie van de linkerbovenhoek van het kaartvenster.width = w+2*x0; hoogte = h+2*y0; van het canvas (iets groter dan b x h) ctx.beginPath(); begin met het tekenen van een polylijn ctx.moveTo(x0+pos.x,y0+pos.y)// ga naar de 0e stad for(var i=1 ; i Voorbeeld van het resultaat van een functieaanroep wordt rechts weergegeven. De betekenis van de tekenopdrachten moet duidelijk zijn uit hun namen en opmerkingen in de code. Eerst wordt een gesloten polylijn getekend (het pad van de handelsreiziger). de stadscirkels en stadsnummers worden er bovenop getekend. Het werken met de sloot in JavaScript is enigszins omslachtig, en dat zal in de toekomst ook gebeuren tekenen, wat dit werk vereenvoudigt en u tegelijkertijd afbeeldingen in SVG-formaat kunt ontvangen.

Overkill in de timer

Het implementeren van een uitgebreid zoekalgoritme voor het vinden van het kortste pad in een timer is niet moeilijk. Om het beste pad in een array op te slaan minweg laten we een functie schrijven voor het kopiëren van de waarden van array-elementen src naar array des:

Functie copy(des, src) ( if(des.length !== src.length) des = new Array(src.length); for(var i=0; i

Het zoeken naar een substring in een string wordt uitgevoerd volgens een bepaald patroon, d.w.z. een reeks tekens waarvan de lengte niet groter is dan de lengte van de originele tekenreeks. De taak van een zoekopdracht is om te bepalen of een string een bepaald patroon bevat en om de locatie (index) in de string aan te geven als er een match wordt gevonden.

Het brute force-algoritme is het eenvoudigste en langzaamste en bestaat uit het controleren van alle tekstposities om te zien of ze overeenkomen met het begin van het patroon. Als het begin van het patroon samenvalt, wordt de volgende letter in het voorbeeld en in de tekst vergeleken, enzovoort, met het meest recente eenvoudige en langzaamste antwoord, of er zo'n element is of niet, zonder aan te geven of het al bestaat gesorteerd op het ontbreken van een volledige overeenkomst van het patroon of het verschil in de volgende letter.

int BFZoeken(char *s, char *p)

voor (int i = 1; strlen(s) - strlen(p); i++)

voor (int j = 1; strlen(p); j++)

als (p[j] != s)

als (j = strlen(p))

De functie BFSearch zoekt naar de subtekenreeks p in de tekenreeks s en retourneert de index van het eerste teken van de subtekenreeks of 0 als de subtekenreeks niet wordt gevonden. Hoewel deze methode, zoals de meeste brute force-methoden, over het algemeen niet effectief is, is deze in sommige situaties zeer acceptabel.

Het snelste algoritme voor algemene doeleinden dat is ontworpen om naar een subtekenreeks in een tekenreeks te zoeken, is het Boyer-Moore-algoritme, ontwikkeld door twee wetenschappers: Boyer (Robert S. Boyer) en Moore (J. Strother Moore), waarvan de essentie is als volgt.

Boyer-Moore-algoritme

De eenvoudigste versie van het Boyer-Moore-algoritme bestaat uit de volgende stappen. De eerste stap is het samenstellen van een tabel met verplaatsingen voor het gewenste monster. Het tafelconstructieproces zal hieronder worden beschreven. Vervolgens worden het begin van de regel en het patroon gecombineerd en begint de controle vanaf het laatste teken van het patroon. Als het laatste teken van het patroon en het corresponderende teken van de lijn wanneer ze op elkaar worden geplaatst, niet overeenkomen, wordt het patroon verschoven ten opzichte van de lijn met de hoeveelheid die is verkregen uit de offsettabel, en wordt de vergelijking opnieuw gemaakt, beginnend bij het laatste teken van de lijn. het patroon. Als de karakters overeenkomen, wordt het voorlaatste karakter van het monster vergeleken, enzovoort. Als alle tekens in het patroon overeenkomen met de over elkaar geplaatste tekens in de tekenreeks, is de subtekenreeks gevonden en is de zoekopdracht voltooid. Als een bepaald teken (niet het laatste) van het patroon niet overeenkomt met het overeenkomstige teken van de string, verschuiven we het patroon één teken naar rechts en beginnen we opnieuw te controleren vanaf het laatste teken. Het hele algoritme wordt uitgevoerd totdat het gewenste patroon voorkomt of het einde van de reeks wordt bereikt.

De mate van verschuiving in het geval van een mismatch van het laatste teken wordt berekend volgens de regel: de verschuiving van het patroon moet minimaal zijn, om het voorkomen van het patroon in de regel niet te missen. Als een bepaald tekenreekskarakter in een patroon voorkomt, wordt het patroon zodanig verschoven dat het tekenreeksteken overeenkomt met de meest rechtse verschijning van dat teken in het patroon. Als het patroon dit teken helemaal niet bevat, wordt het patroon verschoven met een hoeveelheid die gelijk is aan de lengte ervan, zodat het eerste teken van het patroon over het volgende teken van de te testen lijn wordt gelegd.

De offsetwaarde voor elk teken van het patroon hangt alleen af ​​van de volgorde van de tekens in het patroon, dus het is handig om de offsets vooraf te berekenen en op te slaan in de vorm van een eendimensionale array, waarbij elk teken van het alfabet komt overeen met een offset ten opzichte van het laatste teken van het patroon. Laten we al het bovenstaande uitleggen aan de hand van een eenvoudig voorbeeld. Stel dat er een set van vijf karakters is: a, b, c, d, e, en je moet een exemplaar van het patroon “abbad” vinden in de string “abecccacbadbabbad”. De volgende diagrammen illustreren alle fasen van het algoritme:

Verplaatsingstabel voor het “abbad”-monster.

Begin met zoeken. Het laatste teken van het patroon komt niet overeen met het overlay-teken van de string. Verschuif het monster 5 posities naar rechts:

Drie van de voorbeeldsymbolen kwamen overeen, maar de vierde niet. Verschuif het monster naar de juiste positie:

Het laatste teken komt opnieuw niet overeen met het teken van de string. In overeenstemming met de verplaatsingstabel verschuiven we het monster met 2 posities:

Opnieuw verschuiven we het monster met 2 posities:

Nu verschuiven we, in overeenstemming met de tabel, het patroon met één positie en krijgen we het gewenste voorkomen van het patroon:

Laten we het opgegeven algoritme implementeren. Allereerst moet u het gegevenstype van de offsettabel definiëren. Voor een codetabel bestaande uit 256 tekens ziet de structuurdefinitie er als volgt uit:

BMTable MakeBMTable(char *p)

voor (i = 0; ik<= 255; i++) bmt->bmtarr[i] = strlen(p);

voor (i = strlen(p); i<= 1; i--)

als (bmt->bmtarr] == strlen(p))

bmt->bmtarr] = strlen(p)-i;

Laten we nu een functie schrijven die een zoekopdracht uitvoert.

int BMSearch(int startpos, char *s, char *p)

pos = startpos + lp - 1;

terwijl (pos< strlen(s))

als (p != s) pos = pos + bmt->bmtarr];

voor (i = lp - 1; i<= 1; i--)

als (p[i] != s)

return(pos - lp + 1);

De functie BMSearch retourneert de positie van het eerste teken van de eerste keer dat patroon p voorkomt in string s. Als de reeks p in s niet wordt gevonden, retourneert de functie 0. Met de parameter startpos kunt u de positie in string s specificeren waarop de zoekopdracht moet beginnen. Dit kan handig zijn als u alle voorkomens van p in s wilt vinden. Als u vanaf het begin van de tekenreeks wilt zoeken, stelt u startpos in op 1. Als het zoekresultaat niet nul is, stelt u startpos in op de waarde 'vorig resultaat plus patroonlengte' om het volgende voorkomen van p in s te vinden.

Binair (binair) zoeken

Binair zoeken wordt gebruikt wanneer de doorzochte array al is geordend.

De variabelen lb en ub bevatten respectievelijk de linker- en rechtergrenzen van het arraysegment waar het gewenste element zich bevindt. De zoektocht begint altijd met een onderzoek van het middelste element van het segment. Als de gewenste waarde kleiner is dan het middelste element, moet u verder zoeken in de bovenste helft van het segment, waar alle elementen kleiner zijn dan het zojuist aangevinkte element. Met andere woorden, de waarde van ub wordt (m – 1) en in de volgende iteratie wordt de helft van de oorspronkelijke array gecontroleerd. Als resultaat van elke controle wordt het zoekgebied dus gehalveerd. Als er bijvoorbeeld 100 getallen in de array staan, wordt het zoekgebied na de eerste iteratie teruggebracht tot 50 getallen, na de tweede tot 25, na de derde tot 13, na de vierde tot 7, enz. Als de lengte van de array n is, zijn ongeveer log 2 n vergelijkingen voldoende om de array met elementen te doorzoeken.