<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://www.512.cz/skins/common/feed.css?301"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="cs">
		<id>https://www.512.cz/index.php?feed=atom&amp;target=81.201.60.245&amp;title=Speci%C3%A1ln%C3%AD%3AP%C5%99%C3%ADsp%C4%9Bvky%2F81.201.60.245</id>
		<title>FAV wiki - Příspěvky uživatele [cs]</title>
		<link rel="self" type="application/atom+xml" href="https://www.512.cz/index.php?feed=atom&amp;target=81.201.60.245&amp;title=Speci%C3%A1ln%C3%AD%3AP%C5%99%C3%ADsp%C4%9Bvky%2F81.201.60.245"/>
		<link rel="alternate" type="text/html" href="https://www.512.cz/index.php?title=Speci%C3%A1ln%C3%AD:P%C5%99%C3%ADsp%C4%9Bvky/81.201.60.245"/>
		<updated>2026-10-20T20:11:50Z</updated>
		<subtitle>Z FAV wiki</subtitle>
		<generator>MediaWiki 1.17.0</generator>

	<entry>
		<id>https://www.512.cz/index.php?title=Grafov%C3%A9_algoritmy_(cesta_%E2%80%93_Dijkstra,_Floyd-Warshal,_kostra_%E2%80%93_Prim-Jarnik),_reprezentace_grafu_(matice,_seznam_sousednosti),_z%C3%A1klady_kryptografie_(symetrick%C3%A9,_asymetrick%C3%A9_%C5%A1ifrov%C3%A1n%C3%AD)</id>
		<title>Grafové algoritmy (cesta – Dijkstra, Floyd-Warshal, kostra – Prim-Jarnik), reprezentace grafu (matice, seznam sousednosti), základy kryptografie (symetrické, asymetrické šifrování)</title>
		<link rel="alternate" type="text/html" href="https://www.512.cz/index.php?title=Grafov%C3%A9_algoritmy_(cesta_%E2%80%93_Dijkstra,_Floyd-Warshal,_kostra_%E2%80%93_Prim-Jarnik),_reprezentace_grafu_(matice,_seznam_sousednosti),_z%C3%A1klady_kryptografie_(symetrick%C3%A9,_asymetrick%C3%A9_%C5%A1ifrov%C3%A1n%C3%AD)"/>
				<updated>2012-06-02T18:40:37Z</updated>
		
		<summary type="html">&lt;p&gt;81.201.60.245: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;//Detaily viz PPA 11, 12, 13&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Reprezentace grafu ==&lt;br /&gt;
&lt;br /&gt;
'''Seznam sousednosti''' - každý vrchol má seznam svých sousedů. Je-li graf neorientovaný, hrany jsou v seznamech dvakrát&lt;br /&gt;
&lt;br /&gt;
'''Matice sousednosti''' - matice v * v, kde v je pořet vrcholů, a v ní jsou '1' tam, kde je hrana. Na diagonále jsou smyčky, případně ohonocení vrcholů. Pro neorientovaný hraf je matice symetrická.&lt;br /&gt;
&lt;br /&gt;
Graf může mít v*v-1 hran, podle očekávaného počtu se tedy rozhodneme, kterou možnost zvolíme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dijkstrův algoritmus ==&lt;br /&gt;
&lt;br /&gt;
= algoritmus pro hledání nejkratší cesty v ohodnoceném hrafu grafu.&lt;br /&gt;
&lt;br /&gt;
- hrany mají kladné hodnocení&lt;br /&gt;
&lt;br /&gt;
- většinou se bavíme o neorientovaném grafu, funguje však i pro orientované&lt;br /&gt;
&lt;br /&gt;
- probírán 1000x, takže jen opakování:&lt;br /&gt;
&lt;br /&gt;
Máme ohodnocený graf a dva vrcholy, u a v, a hledáme cestu z u do v&lt;br /&gt;
&lt;br /&gt;
Začneme v u, a tomu přiřadíme vzdálenost 0&lt;br /&gt;
&lt;br /&gt;
Podíváme se na všechny okolní body všech již označených bodů&lt;br /&gt;
&lt;br /&gt;
Posuneme se na ten, který má nejkratší vzdálenost od u (tedy musíme do vzdálenosti připočítat i vzdálenost předchozího bodu od počátku. Tohle je extrémně důležité, protože jinak bychom nalezli MST (konkrétně primův algoritmus), a tomu přiřadíme vzdálenost odpovídající součtu vzdálenosti předchozího bodu (od u) a délky cesty tohoto bodu od jeho předchůdce.&lt;br /&gt;
&lt;br /&gt;
Opakujeme 3 a 4, dokud nenalezneme cílový bod v.&lt;br /&gt;
&lt;br /&gt;
kombinace BFS (pro zjištění všech okolních nejkratších cest) a DFS (pro posun po prvcích). Algoritmus zastaví, pokud najde žádanou cestu.&lt;br /&gt;
&lt;br /&gt;
'''Implementace'''&lt;br /&gt;
&lt;br /&gt;
tabulkou, kdy ke každému vrcholu zapisujeme vzdálenosti, vybíráme v každé řádce nejmenší a tu označíme. Vyhledávání minima by bylo však O(v) (projdeme všechny sousedy vrcholu a hledáme nejbližší) pro všechny hrany, tedy celkem O(v2)&lt;br /&gt;
&lt;br /&gt;
jinak, například pomocí prioritní fronty s možností úpravy. všechny nalezené a neoznačené okolní vrcholy umístíme do prioritní fronty s prioritou jejich vzdálenosti (opět jde o součet délky cesty do předchozího bodu a délky cesty od předchozího bodu do vkládaného bodu), vybereme zepředu fronty, ten prvek označíme, zapamatujeme si, odkud jsme na něj přišli pro pozdější rekonstrukci cesty, a vložíme jeho okolní vrcholy. pokud již ve frontě jsou, upravíme jejich prioritu, je li to nutné. Složitost, pokud je fronta implementována haldou, je O(h + v log v), h protože procházíme všechny hrany a v log v protože pro každý vrchol musíme haldu obnovit. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Floyd-Warshallův algoritmus ==&lt;br /&gt;
&lt;br /&gt;
= algoritmus pro hledání nejkratší cesty pro všechny páry (u, v) v grafu.&lt;br /&gt;
&lt;br /&gt;
- Rychlejší, než Dijsktra pro všechny výchozí body (Dijsktra najde od zadaného vrcholu všechny nejkratší cesty, pokud jej na cílovém vrcholu nezastavíme), pokud je graf hustý (tedy hran je v2) -&amp;gt; Dijsktra by byl (pomocí haldy) O(h + v log v), tedy O(v2 + v log v), tedy horší než v3, při implementaci polem dokonce v4&lt;br /&gt;
&lt;br /&gt;
- Složitost O(v3)&lt;br /&gt;
&lt;br /&gt;
'''Algoritmus'''&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Floyd-warshall-1.jpg]] &lt;br /&gt;
&lt;br /&gt;
Pracuje s maticí sousednosti w, kde jsou hrany označeny jejich délkou (cenou, vzdáleností, ...) a nehrany označeny nekonečnem.&lt;br /&gt;
d je matice aktuálne spoctených nejkratších vzdáleností&lt;br /&gt;
mezi je matice nejkratších mezicest, je nainicializována na -1 (null)&lt;br /&gt;
&lt;br /&gt;
V každém kroku algoritmu zjištuji, jestli existuje mezi vrcholy i,j kratší cesta pres vrchol k, pokud ano, nastavím vzdálenost v d[i][j] na novou velikost a do mezi[i][j] zaznamenám vrchol k. V podstatě procházím všechny buňky matice D v kříži, který protíná prvek (i, j). Pokud jsem dříve nalezl optimální cestu do bodu, je tato cesta ideální, pokud neexistuje cesta přímá. (Víme, že v bodě D[i,j] jsou na začátku všechny hrany. Může se ale stát, že existuje kratší cesta přes jiný vrchol, než po hraně v matici sousednosti. Kde tu cestu najdu? Buď končí ve vrcholu i, nebo ve vrcholu j, každopáně bude v řádce j, nebo sloupci i. a jde přes jiný vrchol. Pokud tedy znám cesty z tohoto vrcholu do ostatních vrcholů, můžu najít cestu z vrcholu i do jiného, třeba x, a z x do j tak, že délka z i -&amp;gt; x + x -&amp;gt; j je kratsí, než doposud nalezená nejkratší cesta)&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Floyd-warshall-2.jpg]] &lt;br /&gt;
&lt;br /&gt;
i = 3, j = 4, tedy cesta z i do j. V matici sousednosti byla 10, ale pokud půjdeme z vrcholu 4 do vrcholu 1 a z něj do vrcholu 3, tato cesta bude kratší (9 &amp;lt; 10). Do matice mezi si tedy uložíme vrchol 1 a v matici D (tato) změníme délu nejlepší cesty z i do j na 9 (tmavomodré pole)&lt;br /&gt;
&lt;br /&gt;
// Nechápu, proč je to v přednáškách vysvětleno tak přes ruku. Vždycky. Stačí vždy jen říct jak a proč, a je to hned jasné. Výpis programu v polopascalovskym kodu nikdo nechápe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Prim-Jarníkův algoritmus ==&lt;br /&gt;
&lt;br /&gt;
= algoritmus pro řešení úlohy minimal spanning tree (MST), tedy problému, kdy pro zadaný graf ((ne)orientovaný, ohodnocený) hledáme kostru (strom), která bude mít nejmenší možné celkové ohodnocení (součet ohodnocení hran bude minimální)&lt;br /&gt;
&lt;br /&gt;
- užití - nejlevnější spojení všech uzlů grafu (elektrifikace domů, stavění silnic po povodni, ...). Nejkratší vzdálenost od elektrárny nemusí nutně být nejlepší (pokud je na mapě kratší vzdálenost, ale v cestě je hora, určitě to není nejlepší řešení)&lt;br /&gt;
&lt;br /&gt;
= hledáme pro každá vrchol nejkratší cestu ke stromu&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; neplést si Dijktrou, ten také hledá nejkratší cestu, ale z výchozího vrcholu&lt;br /&gt;
&lt;br /&gt;
Obrázek naznačí rozdíl:&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Prim-jarnik.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dijsktra použije hranu 4-&amp;gt;5, protože pak bude vždálenost 5 od 1 = 4 ( s hranou 3 -&amp;gt; 5 by byla 5)&lt;br /&gt;
Prim použije hranu 3-&amp;gt;5, protože je levnější, než hrana 4 -&amp;gt; 5, a tedy hodnota stromu je 7, což je menší než 8.&lt;br /&gt;
&lt;br /&gt;
Tím je vlastně i popsán algoritmus. Je podobný jako Dijsktra, ale v bodě 4 kontrolujeme pouze váhu hrany, níkoliv součet cesty do předchozího bodu a váhy. Implementace je stejná, řadíme podle vah hran (opět ignorujeme předchozí cesty)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Základy kryptografie ==&lt;br /&gt;
&lt;br /&gt;
Šifrujeme, protože nechceme, aby třetí osoba věděla, o co se jedná&lt;br /&gt;
&lt;br /&gt;
ochrana citlivých přenášených dat&lt;br /&gt;
&lt;br /&gt;
ochrana před odposlechem&lt;br /&gt;
&lt;br /&gt;
ochrana před neautorizovaným přístupem&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
'''Šifrování''' = transformace dat do nečitelné podoby&lt;br /&gt;
&lt;br /&gt;
'''Dešifrování''' = zpětný proces rekonstrukce šifrované zprávy pomocí tajného klíče&lt;br /&gt;
&lt;br /&gt;
'''Kryptografie''' - věda o tvorbě šifer&lt;br /&gt;
&lt;br /&gt;
'''Kryptoanalýza ''' - věda o prolamování šifer (nejjednodušší: frekvenční analýza. Anglické texty obsahují velké množství výskytů slova THE, můžeme tedy dedukovat, že nejčastější 3 písmenná slova substitučně šifrovaného textu jsou právě THE (například PQX), a můžeme tyto písmena použít (T-&amp;gt;P, H-&amp;gt;Q, E-&amp;gt;X)&lt;br /&gt;
&lt;br /&gt;
'''Dělění'''&lt;br /&gt;
&lt;br /&gt;
[[Z hlediska zpracování zprávy:]] &lt;br /&gt;
&lt;br /&gt;
''Blokové šifry'' - pracují s celými bloky dat  (obvykle  8-128 bytů)&lt;br /&gt;
&lt;br /&gt;
''Proudové šifry (streamové)'' - pracují s jednotlivými bitu zprávy zvlášť, jsou považovány za méně bezpečné, jsou pomalejší než šifry blokové&lt;br /&gt;
&lt;br /&gt;
[[Z hlediska šifrování:]]&lt;br /&gt;
&lt;br /&gt;
''Symetrické šifry'' - odesilatel i příjemce sdílí jedno tajemství (klíč) nutné k šifrování a zašifrování zprávy&lt;br /&gt;
&lt;br /&gt;
''Asymetrické šifry'' - odesilatel a příjemci šifrují a dešifrují zprávu různými klíči, nemusí spolu sdílet žádné tajemství. Nevýhoda:  je o několik řádů pomalejší než symetrická kryptografie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Symetricky'''&lt;br /&gt;
&lt;br /&gt;
Je nejpoužívanějším typem šifrovacího algoritmu&lt;br /&gt;
&lt;br /&gt;
Používá stejný šifrovací klíč k šifrování i dešifrování- což je jeho největší slabina&lt;br /&gt;
&lt;br /&gt;
Je velmi rychlý a používá se při velkém množství dat&lt;br /&gt;
&lt;br /&gt;
Klíč se musí dostat od odesilatele k adresátovi bezpečným kanálem (cestou), aby adresát mohl zprávu dešifrovat. Často osobní předání.&lt;br /&gt;
Pokud takový bezpečný kanál existuje, je často jednodušší zprávu nešifrovat a poslat ji rovnou tímto kanálem. &lt;br /&gt;
&lt;br /&gt;
Příklady: AES (ve wifi, je nutné fyzicky zadat klíč do zařízení i do pořítače), A5 (v mobilních telefonech, klíč je na SIM a u uperátora) a DES (nejpoužívanější šifra na světě)&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Symetricke-sifrovani.jpg]] &lt;br /&gt;
&lt;br /&gt;
'''Nesymetricky'''&lt;br /&gt;
&lt;br /&gt;
Používá jiný klíč k zašifrování a jiný klíč zpátky k dešifrování&lt;br /&gt;
&lt;br /&gt;
První z nich se nazývá veřejný, ostatní ho musejí znát. Druhý klíč se nazývá privátní&lt;br /&gt;
&lt;br /&gt;
Asymetrický šifrovací systém (systém s veřejným klíčem) je založen na principu jednocestné funkce, což jsou operace, které lze snadno provést pouze v jednom směru: ze vstupu lze snadno spočítat výstup, z výstupu však je velmi obtížné nalézt vstup. &lt;br /&gt;
Nejběžnějším příkladem je například násobení: je velmi snadné vynásobit dvě i velmi velká čísla, avšak rozklad součinu na činitele (tzv. faktorizace) je velmi obtížný. (Na tomto problému je založen např. algoritmus RSA.)&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Asymetricke-sifrovani.jpg]]&lt;/div&gt;</summary>
		<author><name>81.201.60.245</name></author>	</entry>

	<entry>
		<id>https://www.512.cz/index.php?title=Algoritmy_zpracov%C3%A1n%C3%AD_text%C5%AF_%E2%80%93_operace_s_%C5%99et%C4%9Bzci,_porovn%C3%A1n%C3%AD_se_vzorem_(KMP,_Boyer-Moore_algoritmus),_nejdel%C5%A1%C3%AD_spole%C4%8Dn%C3%BD_pod%C5%99et%C4%9Bzec_(LCS_algoritmus),_vzd%C3%A1lenost_mezi_%C5%99et%C4%9Bzci,_datov%C3%A1_struktura_Trie_a_pou%C5%BEit%C3%AD</id>
		<title>Algoritmy zpracování textů – operace s řetězci, porovnání se vzorem (KMP, Boyer-Moore algoritmus), nejdelší společný podřetězec (LCS algoritmus), vzdálenost mezi řetězci, datová struktura Trie a použití</title>
		<link rel="alternate" type="text/html" href="https://www.512.cz/index.php?title=Algoritmy_zpracov%C3%A1n%C3%AD_text%C5%AF_%E2%80%93_operace_s_%C5%99et%C4%9Bzci,_porovn%C3%A1n%C3%AD_se_vzorem_(KMP,_Boyer-Moore_algoritmus),_nejdel%C5%A1%C3%AD_spole%C4%8Dn%C3%BD_pod%C5%99et%C4%9Bzec_(LCS_algoritmus),_vzd%C3%A1lenost_mezi_%C5%99et%C4%9Bzci,_datov%C3%A1_struktura_Trie_a_pou%C5%BEit%C3%AD"/>
				<updated>2012-06-01T21:52:54Z</updated>
		
		<summary type="html">&lt;p&gt;81.201.60.245: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tak tahle otázka je očistec. Kdo tohle všechno vysvětlí za 15 minut je borec, i když bych řekl, že je tam rozsekaj na menší otázky.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Obecně ==&lt;br /&gt;
&lt;br /&gt;
Vyhledáváme podřetězec P v řetězci T. T je string s textem, P je string s maskou (pattern)&lt;br /&gt;
&lt;br /&gt;
Podřetězec je část řetězce [i..j]. T je délky n, P je délky m.&lt;br /&gt;
&lt;br /&gt;
Prefix je část řetězce (či podřetězce) od začátku, suffix je část řetězce (či podřetězce) od konce.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Brutální síla ==&lt;br /&gt;
&lt;br /&gt;
Indexem jdeme po T a kontrolujeme, jestli podřetězec začínající na tomto indexu neodpovídá P (tedy kontrolujeme m prvků od indexu směrem do prava.&lt;br /&gt;
V nejhorším případě O(nm), což je pomalé&lt;br /&gt;
&lt;br /&gt;
	T: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah&lt;br /&gt;
&lt;br /&gt;
	P: aah&lt;br /&gt;
&lt;br /&gt;
	P v T najdeme až úplně na konci, pro každé 'a' v T (kromě třetího od konce) znovu hledáme písmena P v řetězci T zcela zbytečně&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Boyer-Moore (BM) algoritmus ==&lt;br /&gt;
&lt;br /&gt;
V tomto algoritmu prohledáváme P od konce, a hledáme výskyt v T. Do T ukazuje index i, do P index j.&lt;br /&gt;
&lt;br /&gt;
Mohou nastat 4 případy:&lt;br /&gt;
&lt;br /&gt;
1) T[i] není v P vůbec, posuneme i dále o délku P (zarovnáme P na další písmeno v T, tedy T[i+1]&lt;br /&gt;
&lt;br /&gt;
(obrázky v přednáškách jsou křivé, tak se mi to snad povedlo odstranit)&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Boyer-moore-1.jpg]]&lt;br /&gt;
&lt;br /&gt;
2) T[i] odpovídá P[j] - posuneme se v obou do leva a opakujeme (jako v brutální síle)&lt;br /&gt;
&lt;br /&gt;
3) T[i] není P[j], ale T[i] je v P před indexem j -&amp;gt; zarovnáme P do prava tak, aby T[i] odpovídal jeho výskytu v P a opakujeme&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Boyer-moore-2.jpg]] &lt;br /&gt;
&lt;br /&gt;
4) T[i] není P[j], ale T[i] je v P za indexem j -&amp;gt; posuneme se do prava o 1 a opakujeme (nemůžeme se vracet, ale ani posunout o více dále)&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Boyer-moore-3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Pokud nalezneme celý pattern, vrátíme i. Algoritmus je pro texty rychlejší, než brute force, i tak je však jeho složitost O(mn + A), kde A je velikost abecedy. Pro velké abecedy funguje rychle, ale např pro binární soubory funguje pomalu.&lt;br /&gt;
&lt;br /&gt;
'''Dodatek:''' Algoritmus si v preprocesingu zjistí, na které pozici má které písmena (směrem od leva). Je-li patern tedy například &amp;quot;ABRAKADABRA&amp;quot;, A dostane index 10, B dostane index 8, K = 4, D = 6 a R = 9. Pro ostatní písmena přiřadíme -1. Naimplementujeme tedy funkci Last(char input), která podle písmene vrátí tento index, a pak pro případy 3 a 4 porovnáváme Last(T[i]) a j, a tím pak víme, jestli i posunout na Last(T[i]) (pokud je Last(T[i]) &amp;lt; j) nebo pouze i++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Knuth‐Morris‐Pratt (KMP) algoritmus ==&lt;br /&gt;
&lt;br /&gt;
Jako brutal force jde zleva do prava, ale nedělá otrocky všechny porovnání. Pokud narazíme na neshodu, je možné se posunout o více než o jedno písmeno. &lt;br /&gt;
&lt;br /&gt;
Otázka zní o kolik?&lt;br /&gt;
&lt;br /&gt;
Odpověď, o maximální prefix P( 0 .. j-1 ), který je suffixem P( 1 .. j-1 ). Suffix a prefix se nesmí překrývat.&lt;br /&gt;
&lt;br /&gt;
Proč? Protože najdeme-li kus P (od začátku, tedy prefix), víme, že znaky tohoto prefixu odpovídají textu. Je tedy netřeba je kontrolovat znovu. Může se ale stát, že konec nalezeného podřetězce je také obsažen v začátku tohoto podřetězce. Takovou shodou je samozřejmě celá nalezená část P, proto hledáme od P+1. Takže jdeme od konce nalezeného kusu P zleva a zprava, a ve chvíli, kdy nenalezneme shodu, víme, o kolik se můžeme posunout. Tohle se samozřejmě dá předpočítat do tabulky, a pak je vše O(1)&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Kmp.jpg]]&lt;br /&gt;
&lt;br /&gt;
(i.e. P[j] != T[i]), pak&lt;br /&gt;
k = j‐1;&lt;br /&gt;
j = F(k); // získání nové hodnoty j, kde F(k) je právě předpočítaná tabulka společných částí P&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Trie ==&lt;br /&gt;
&lt;br /&gt;
Trie je struktura pro předspracování textu pro pozdější rychlé vyhledávání. V každém uzlu standartní Trie je písmeno a délka cesty k vrcholu je také pozicí písmene ve slově, tedy je-li hloubka písmene 'E' v Trie rovna 3, víme, že je to třetí písmeno (např. slova Trie)&lt;br /&gt;
&lt;br /&gt;
Standartní trie má v každém uzlu právě jedno písmeno. Vyhledávání je O(d * m) kde d je velikost abecedy (v každém uzlu musíme projít všechna písmena, abychom zjistili, že tam písmeno je), m je délka slova. Paměťově je Trie nejvýše složitosti O(n) kde n je délka původního textu. Pokud se slova překrývají, paměťi je potřeba méně.&lt;br /&gt;
&lt;br /&gt;
Rychlost se dá na úkor paměti vylepšit tak, že v každém uzlu připravíme celou abecedu a při hledání převedeme písmeno na index v této abecedě, tím pádem záskáme v O(1) čase pointer na další písmeno ve slově.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Komprimovaná trie ==&lt;br /&gt;
&lt;br /&gt;
Jako trie, ale sklukujeme, tedy ve vrcholech stromu písmena, která jsou společná pro všechna slova, tedy pro slova 'ahoj' a 'ahojky' bude mít trie 2 vrcholy, 'ahoj' a pod ním 'ahojky'. Tuto Trie lze převést na standartní pouhým rozdělením shluků, standartní Trie převedeme na kompaktní sloučením vrcholů s rodiči, kteří mají pouze jeden odkaz na vrchol (tento vrchol)&lt;br /&gt;
&lt;br /&gt;
Pak je ještě suffixová Trie, které ukládá všechny sufixy slov, v komprimované podobě. Umožňuje vyhledávat i uprostřed slova.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LCS - Longest common subsequence ==&lt;br /&gt;
&lt;br /&gt;
Tohle je skoro nemožný vysvetlit na statickym papiru....&lt;br /&gt;
&lt;br /&gt;
Cílem algoritmu je najít nejdelší společný podřetězec libovolného počtu řetězců. To je problém NP-těžký, což je masakr. &lt;br /&gt;
My se ale omezíme na porovnávání 2 řezězců, což je v polynomiálním čase řešitelné (dynamicky).&lt;br /&gt;
&lt;br /&gt;
Brutální síla by dělala to, že by našla všechny podřetězce obou řetězců, a ty porovnávala (také brutální silou) Podřetězců je však řekněme n!, brutální síla je n2, takže (n!)2. Dynamicky to lze dělat rychleji. Použijeme tedy rovnou dynamické programování, protože to nám dovoluje pamatovat si so už jsme našli, a neztrácet čas znovuobjevováním nalezeného.&lt;br /&gt;
&lt;br /&gt;
Nechť Li,j = maximální délka společných řetězců končících v Ai a Bj . Vytvoříme si tedy dvojrozměrnou tabulku, do které si tyto Li,j budeme zapisovat.&lt;br /&gt;
&lt;br /&gt;
Nyní, je-li písmeno na pozici i v řetězci A stejné, jako písmeno na pozici j v řetezci B, víme, že jde o společný podřetězec (délky 1). Nevíme však, zda předchozí písmena nebyla také podřetězcem (zatím)&lt;br /&gt;
&lt;br /&gt;
Víme ale následující: Pokud existoval pořetezec pro indexy i-1 a j-1 (tedy pro předchozí písmena v obou řetězcích), bude v tabulce na příslušné pozici, tedy vlevo nahoře od Li,j tedy  Li-1,j-1. Na této pozici je tím pádem dosavadně nalezená délka společného podřetězce, který končí na indexech i-1 a j-1. Pokud by i předchozí indexy daly stejné písmeno, musíme tuto délku dále diagonálně propagovat, a tedy&lt;br /&gt;
&lt;br /&gt;
Ai = Bj -&amp;gt; Li,j = Li-1,j-1 + 1 -&amp;gt; společný řetězec končící na indexu i-1,j-1 pokračuje&lt;br /&gt;
&lt;br /&gt;
Ai &amp;lt;&amp;gt; Bj -&amp;gt; Li,j = 0 -&amp;gt; není společný (pokud na i-1 a j-1 byl, na tomto indexu končí)&lt;br /&gt;
&lt;br /&gt;
Takto vyplníme celou tabulku, přičemž nulté řádky budou nulové (abychom nevyšli pro první písmena z hranice pole)&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Lcs.jpg]]&lt;br /&gt;
&lt;br /&gt;
Problém: Jak zjistit, kde je řešení nejlepší? Ano, můžeme najít maximum v tabulce, ale to je další O(M + N) operace, a máme tabulku plnou nul, toho lze využít. Algoritmus tedy modifikujeme tak, že bude zachovávat i dosavadně nejlepší nalezenou délku společného podřetězce v každém bodě. toho docílíme úpravou druhého pravidla, tedy&lt;br /&gt;
&lt;br /&gt;
Ai = Bj -&amp;gt; Li,j = Li-1,j-1 + 1&lt;br /&gt;
Ai &amp;lt;&amp;gt; Bj -&amp;gt; Li,j = max (Li-1,j, Li,j-1)&lt;br /&gt;
&lt;br /&gt;
Nejlepší nalezené řešení je nahoře, nebo vlevo. Tím se tabulka naplní, a my budeme znát nejlepší délku v pravém spodním rohu tabulky&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Lcs-2.jpg]] &lt;br /&gt;
&lt;br /&gt;
Nyní ale nevíme, kde ta písmena jsou. Je tedy nutné si to ukládat do druhé tabulky (onačit si, kudy jsme na které pole přišli, z leva, ze shora (při zpětném průchodu pouze posun), nebo šikmo (při zpětném průchodu výpis a posun)) a následně zrekonstruovat zpětným průchodem. V přednáškách jsou šipky, ukazující kudy se budeme vracet. Při provádění pravidla 2 si samozřejmě tuto informaci musíme také propagovat, pomatujeme si tedy, odkud jsme na každé pole přišli ( v druhé tabulce si to lze označit třeba 0, 1 pro nahoru a do leva, 2 pro šikmo )&lt;br /&gt;
&lt;br /&gt;
A konečně...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Vzdálenost mezi řetězci ==&lt;br /&gt;
&lt;br /&gt;
'''Hammingova metrika:''' na stejně dlouhé řetězce, jen je porovnáme, a v O(n) čase víme, kolik změn písmen musíme provést (Auto, Zutá = 2)&lt;br /&gt;
&lt;br /&gt;
'''Levensteinova metrika:''' někdy také edit distance, máme operace změnit/přidat/odebrat písmeno, abychom dostali z jednoho řetězce ten druhý. Jde o celočíselné vyjádření podobnosti řetězců, například&lt;br /&gt;
&lt;br /&gt;
P=abcdefghijkl, T=bcdeffghixkl, P odpovídá T po 3 změnách (v T přidat a, ubrat f a zaměnit x za j)&lt;br /&gt;
&lt;br /&gt;
'''Algoritmus:'''&lt;br /&gt;
Postup podobný jako u LCS, ale&lt;br /&gt;
matice je D[i,j]&lt;br /&gt;
a prvky vyplňujeme takto &lt;br /&gt;
&lt;br /&gt;
máme 3 možné způsoby úpravy řetězce&lt;br /&gt;
&lt;br /&gt;
1. P[i]=T[j] , s = D[i-1,j-1] (shoda) jinak D[i-1,j-1] + 1 (substituce, platíme cenu za změnu znaku)&lt;br /&gt;
&lt;br /&gt;
2. v = D[i-1,j] + 1 (znak navíc v P, neposouváme pointer v T (při úpravách) a platíme cenu za vkládání)&lt;br /&gt;
&lt;br /&gt;
3. r = D[i,j-1] + 1 (znak navíc v T, neposouváme pointer v P (při úpravách) a platíme cenu za rušení)&lt;br /&gt;
&lt;br /&gt;
minimem z s, v a r  získáme pole D[i,j]&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Vzdalenost-mezi-retezci.jpg]]&lt;br /&gt;
&lt;br /&gt;
Řešení je opšt ve spodním pravém rohu a zpět postupujeme po stejných číslech (žádná změna) nebo menších (změna, jdeme-li šikmo, substituce, jdeme-li nahoru rušení, do leva vkládání)&lt;/div&gt;</summary>
		<author><name>81.201.60.245</name></author>	</entry>

	<entry>
		<id>https://www.512.cz/index.php?title=Algoritmy_zpracov%C3%A1n%C3%AD_text%C5%AF_%E2%80%93_operace_s_%C5%99et%C4%9Bzci,_porovn%C3%A1n%C3%AD_se_vzorem_(KMP,_Boyer-Moore_algoritmus),_nejdel%C5%A1%C3%AD_spole%C4%8Dn%C3%BD_pod%C5%99et%C4%9Bzec_(LCS_algoritmus),_vzd%C3%A1lenost_mezi_%C5%99et%C4%9Bzci,_datov%C3%A1_struktura_Trie_a_pou%C5%BEit%C3%AD</id>
		<title>Algoritmy zpracování textů – operace s řetězci, porovnání se vzorem (KMP, Boyer-Moore algoritmus), nejdelší společný podřetězec (LCS algoritmus), vzdálenost mezi řetězci, datová struktura Trie a použití</title>
		<link rel="alternate" type="text/html" href="https://www.512.cz/index.php?title=Algoritmy_zpracov%C3%A1n%C3%AD_text%C5%AF_%E2%80%93_operace_s_%C5%99et%C4%9Bzci,_porovn%C3%A1n%C3%AD_se_vzorem_(KMP,_Boyer-Moore_algoritmus),_nejdel%C5%A1%C3%AD_spole%C4%8Dn%C3%BD_pod%C5%99et%C4%9Bzec_(LCS_algoritmus),_vzd%C3%A1lenost_mezi_%C5%99et%C4%9Bzci,_datov%C3%A1_struktura_Trie_a_pou%C5%BEit%C3%AD"/>
				<updated>2012-06-01T21:11:33Z</updated>
		
		<summary type="html">&lt;p&gt;81.201.60.245: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tak tahle otázka je očistec. Kdo tohle všechno vysvětlí za 15 minut je borec, i když bych řekl, že je tam rozsekaj na menší otázky.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obecně:&lt;br /&gt;
&lt;br /&gt;
Vyhledáváme podřetězec P v řetězci T. T je string s textem, P je string s maskou (pattern)&lt;br /&gt;
&lt;br /&gt;
Podřetězec je část řetězce [i..j]. T je délky n, P je délky m.&lt;br /&gt;
&lt;br /&gt;
Prefix je část řetězce (či podřetězce) od začátku, suffix je část řetězce (či podřetězce) od konce.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Brutální síla: ==&lt;br /&gt;
&lt;br /&gt;
Indexem jdeme po T a kontrolujeme, jestli podřetězec začínající na tomto indexu neodpovídá P (tedy kontrolujeme m prvků od indexu směrem do prava.&lt;br /&gt;
V nejhorším případě O(nm), což je pomalé&lt;br /&gt;
&lt;br /&gt;
	T: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah&lt;br /&gt;
&lt;br /&gt;
	P: aah&lt;br /&gt;
&lt;br /&gt;
	P v T najdeme až úplně na konci, pro každé 'a' v T (kromě třetího od konce) znovu hledáme písmena P v řetězci T zcela zbytečně&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Boyer-Moore (BM) algoritmus: ==&lt;br /&gt;
&lt;br /&gt;
V tomto algoritmu prohledáváme P od konce, a hledáme výskyt v T. Do T ukazuje index i, do P index j.&lt;br /&gt;
&lt;br /&gt;
Mohou nastat 4 případy:&lt;br /&gt;
&lt;br /&gt;
1) T[i] není v P vůbec, posuneme i dále o délku P (zarovnáme P na další písmeno v T, tedy T[i+1]&lt;br /&gt;
&lt;br /&gt;
(obrázky v přednáškách jsou křivé, tak se mi to snad povedlo odstranit)&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Boyer-moore-1.jpg]]&lt;br /&gt;
&lt;br /&gt;
2) T[i] odpovídá P[j] - posuneme se v obou do leva a opakujeme (jako v brutální síle)&lt;br /&gt;
&lt;br /&gt;
3) T[i] není P[j], ale T[i] je v P před indexem j -&amp;gt; zarovnáme P do prava tak, aby T[i] odpovídal jeho výskytu v P a opakujeme&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Boyer-moore-2.jpg]] &lt;br /&gt;
&lt;br /&gt;
4) T[i] není P[j], ale T[i] je v P za indexem j -&amp;gt; posuneme se do prava o 1 a opakujeme (nemůžeme se vracet, ale ani posunout o více dále)&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Boyer-moore-3.jpg]]&lt;br /&gt;
&lt;br /&gt;
Pokud nalezneme celý pattern, vrátíme i. Algoritmus je pro texty rychlejší, než brute force, i tak je však jeho složitost O(mn + A), kde A je velikost abecedy. Pro velké abecedy funguje rychle, ale např pro binární soubory funguje pomalu.&lt;br /&gt;
&lt;br /&gt;
'''Dodatek:''' Algoritmus si v preprocesingu zjistí, na které pozici má které písmena (směrem od leva). Je-li patern tedy například &amp;quot;ABRAKADABRA&amp;quot;, A dostane index 10, B dostane index 8, K = 4, D = 6 a R = 9. Pro ostatní písmena přiřadíme -1. Naimplementujeme tedy funkci Last(char input), která podle písmene vrátí tento index, a pak pro případy 3 a 4 porovnáváme Last(T[i]) a j, a tím pak víme, jestli i posunout na Last(T[i]) (pokud je Last(T[i]) &amp;lt; j) nebo pouze i++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Knuth‐Morris‐Pratt (KMP) algoritmus ==&lt;br /&gt;
&lt;br /&gt;
Jako brutal force jde zleva do prava, ale nedělá otrocky všechny porovnání. Pokud narazíme na neshodu, je možné se posunout o více než o jedno písmeno. &lt;br /&gt;
&lt;br /&gt;
Otázka zní o kolik?&lt;br /&gt;
&lt;br /&gt;
Odpověď, o maximální prefix P( 0 .. j-1 ), který je suffixem P( 1 .. j-1 ). Suffix a prefix se nesmí překrývat.&lt;br /&gt;
&lt;br /&gt;
Proč? Protože najdeme-li kus P (od začátku, tedy prefix), víme, že znaky tohoto prefixu odpovídají textu. Je tedy netřeba je kontrolovat znovu. Může se ale stát, že konec nalezeného podřetězce je také obsažen v začátku tohoto podřetězce. Takovou shodou je samozřejmě celá nalezená část P, proto hledáme od P+1. Takže jdeme od konce nalezeného kusu P zleva a zprava, a ve chvíli, kdy nenalezneme shodu, víme, o kolik se můžeme posunout. Tohle se samozřejmě dá předpočítat do tabulky, a pak je vše O(1)&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Kmp.jpg]]&lt;br /&gt;
&lt;br /&gt;
(i.e. P[j] != T[i]), pak&lt;br /&gt;
k = j‐1;&lt;br /&gt;
j = F(k); // získání nové hodnoty j, kde F(k) je právě předpočítaná tabulka společných částí P&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Trie. ==&lt;br /&gt;
&lt;br /&gt;
Trie je struktura pro předspracování textu pro pozdější rychlé vyhledávání. V každém uzlu standartní Trie je písmeno a délka cesty k vrcholu je také pozicí písmene ve slově, tedy je-li hloubka písmene 'E' v Trie rovna 3, víme, že je to třetí písmeno (např. slova Trie)&lt;br /&gt;
&lt;br /&gt;
Standartní trie má v každém uzlu právě jedno písmeno. Vyhledávání je O(d * m) kde d je velikost abecedy (v každém uzlu musíme projít všechna písmena, abychom zjistili, že tam písmeno je), m je délka slova. Paměťově je Trie nejvýše složitosti O(n) kde n je délka původního textu. Pokud se slova překrývají, paměťi je potřeba méně.&lt;br /&gt;
&lt;br /&gt;
Rychlost se dá na úkor paměti vylepšit tak, že v každém uzlu připravíme celou abecedu a při hledání převedeme písmeno na index v této abecedě, tím pádem záskáme v O(1) čase pointer na další písmeno ve slově.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Komprimovaná trie: ==&lt;br /&gt;
&lt;br /&gt;
Jako trie, ale sklukujeme, tedy ve vrcholech stromu písmena, která jsou společná pro všechna slova, tedy pro slova 'ahoj' a 'ahojky' bude mít trie 2 vrcholy, 'ahoj' a pod ním 'ahojky'. Tuto Trie lze převést na standartní pouhým rozdělením shluků, standartní Trie převedeme na kompaktní sloučením vrcholů s rodiči, kteří mají pouze jeden odkaz na vrchol (tento vrchol)&lt;br /&gt;
&lt;br /&gt;
Pak je ještě suffixová Trie, které ukládá všechny sufixy slov, v komprimované podobě. Umožňuje vyhledávat i uprostřed slova.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LCS - Longest common subsequence ==&lt;br /&gt;
&lt;br /&gt;
Tohle je skoro nemožný vysvetlit na statickym papiru....&lt;br /&gt;
&lt;br /&gt;
Cílem algoritmu je najít nejdelší společný podřetězec libovolného počtu řetězců. To je problém NP-těžký, což je masakr. &lt;br /&gt;
My se ale omezíme na porovnávání 2 řezězců, což je v polynomiálním čase řešitelné (dynamicky).&lt;br /&gt;
&lt;br /&gt;
Brutální síla by dělala to, že by našla všechny podřetězce obou řetězců, a ty porovnávala (také brutální silou) Podřetězců je však řekněme n!, brutální síla je n2, takže (n!)2. Dynamicky to lze dělat rychleji. Použijeme tedy rovnou dynamické programování, protože to nám dovoluje pamatovat si so už jsme našli, a neztrácet čas znovuobjevováním nalezeného.&lt;br /&gt;
&lt;br /&gt;
Nechť Li,j = maximální délka společných řetězců končících v Ai a Bj . Vytvoříme si tedy dvojrozměrnou tabulku, do které si tyto Li,j budeme zapisovat.&lt;br /&gt;
&lt;br /&gt;
Nyní, je-li písmeno na pozici i v řetězci A stejné, jako písmeno na pozici j v řetezci B, víme, že jde o společný podřetězec (délky 1). Nevíme však, zda předchozí písmena nebyla také podřetězcem (zatím)&lt;br /&gt;
&lt;br /&gt;
Víme ale následující: Pokud existoval pořetezec pro indexy i-1 a j-1 (tedy pro předchozí písmena v obou řetězcích), bude v tabulce na příslušné pozici, tedy vlevo nahoře od Li,j tedy  Li-1,j-1. Na této pozici je tím pádem dosavadně nalezená délka společného podřetězce, který končí na indexech i-1 a j-1. Pokud by i předchozí indexy daly stejné písmeno, musíme tuto délku dále diagonálně propagovat, a tedy&lt;br /&gt;
&lt;br /&gt;
Ai = Bj -&amp;gt; Li,j = Li-1,j-1 + 1 -&amp;gt; společný řetězec končící na indexu i-1,j-1 pokračuje&lt;br /&gt;
&lt;br /&gt;
Ai &amp;lt;&amp;gt; Bj -&amp;gt; Li,j = 0 -&amp;gt; není společný (pokud na i-1 a j-1 byl, na tomto indexu končí)&lt;br /&gt;
&lt;br /&gt;
Takto vyplníme celou tabulku, přičemž nulté řádky budou nulové (abychom nevyšli pro první písmena z hranice pole)&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Lcs.jpg]]&lt;br /&gt;
&lt;br /&gt;
Problém: Jak zjistit, kde je řešení nejlepší? Ano, můžeme najít maximum v tabulce, ale to je další O(M + N) operace, a máme tabulku plnou nul, toho lze využít. Algoritmus tedy modifikujeme tak, že bude zachovávat i dosavadně nejlepší nalezenou délku společného podřetězce v každém bodě. toho docílíme úpravou druhého pravidla, tedy&lt;br /&gt;
&lt;br /&gt;
Ai = Bj -&amp;gt; Li,j = Li-1,j-1 + 1&lt;br /&gt;
Ai &amp;lt;&amp;gt; Bj -&amp;gt; Li,j = max (Li-1,j, Li,j-1)&lt;br /&gt;
&lt;br /&gt;
Nejlepší nalezené řešení je nahoře, nebo vlevo. Tím se tabulka naplní, a my budeme znát nejlepší délku v pravém spodním rohu tabulky&lt;br /&gt;
&lt;br /&gt;
[[Soubor:Lcs-2.jpg]] &lt;br /&gt;
&lt;br /&gt;
Nyní ale nevíme, kde ta písmena jsou. Je tedy nutné si to ukládat do druhé tabulky (onačit si, kudy jsme na které pole přišli, z leva, ze shora (při zpětném průchodu pouze posun), nebo šikmo (při zpětném průchodu výpis a posun)) a následně zrekonstruovat zpětným průchodem. V přednáškách jsou šipky, ukazující kudy se budeme vracet. Při provádění pravidla 2 si samozřejmě tuto informaci musíme také propagovat, pomatujeme si tedy, odkud jsme na každé pole přišli ( v druhé tabulce si to lze označit třeba 0, 1 pro nahoru a do leva, 2 pro šikmo )&lt;br /&gt;
&lt;br /&gt;
A konečně...&lt;br /&gt;
&lt;br /&gt;
Vzdálenost mezi řetězci:&lt;br /&gt;
&lt;br /&gt;
'''Hammingova metrika:''' na stejně dlouhé řetězce, jen je porovnáme, a v O(n) čase víme, kolik změn písmen musíme provést (Auto, Zutá = 2)&lt;br /&gt;
'''Levensteinova metrika:''' někdy také edit distance, máme operace změnit/přidat/odebrat písmeno, abychom dostali z jednoho řetězce ten druhý. Jde o celočíselné vyjádření podobnosti řetězců, například&lt;br /&gt;
&lt;br /&gt;
P=abcdefghijkl, T=bcdeffghixkl, P odpovídá T po 3 změnách (v T přidat a, ubrat f a zaměnit x za j)&lt;br /&gt;
&lt;br /&gt;
'''Algoritmus:'''&lt;br /&gt;
Postup podobný jako u LCS, ale&lt;br /&gt;
matice je D[i,j]&lt;br /&gt;
a prvky vyplňujeme takto &lt;br /&gt;
&lt;br /&gt;
máme 3 možné způsoby úpravy řetězce&lt;br /&gt;
&lt;br /&gt;
1. P[i]=T[j] , s = D[i-1,j-1] (shoda) jinak D[i-1,j-1] + 1 (substituce, platíme cenu za změnu znaku)&lt;br /&gt;
&lt;br /&gt;
2. v = D[i-1,j] + 1 (znak navíc v P, neposouváme pointer v T (při úpravách) a platíme cenu za vkládání)&lt;br /&gt;
&lt;br /&gt;
3. r = D[i,j-1] + 1 (znak navíc v T, neposouváme pointer v P (při úpravách) a platíme cenu za rušení)&lt;br /&gt;
&lt;br /&gt;
minimem z s, v a r  získáme pole D[i,j]&lt;br /&gt;
 &lt;br /&gt;
[[Soubor:Vzdalenost-mezi-retezci.jpg]]&lt;br /&gt;
&lt;br /&gt;
Řešení je opšt ve spodním pravém rohu a zpět postupujeme po stejných číslech (žádná změna) nebo menších (změna, jdeme-li šikmo, substituce, jdeme-li nahoru rušení, do leva vkládání)&lt;/div&gt;</summary>
		<author><name>81.201.60.245</name></author>	</entry>

	<entry>
		<id>https://www.512.cz/index.php?title=Tabulky_s_rozpt%C3%BDlen%C3%BDmi_polo%C5%BEkami,_vyhled%C3%A1v%C3%A1n%C3%AD_v_tabulk%C3%A1ch</id>
		<title>Tabulky s rozptýlenými položkami, vyhledávání v tabulkách</title>
		<link rel="alternate" type="text/html" href="https://www.512.cz/index.php?title=Tabulky_s_rozpt%C3%BDlen%C3%BDmi_polo%C5%BEkami,_vyhled%C3%A1v%C3%A1n%C3%AD_v_tabulk%C3%A1ch"/>
				<updated>2012-06-01T18:19:24Z</updated>
		
		<summary type="html">&lt;p&gt;81.201.60.245: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To samé jako PPA2 14 a 15,&lt;br /&gt;
&lt;br /&gt;
jen doplňky/opakování/upřesnění:&lt;br /&gt;
&lt;br /&gt;
'''Vnitřní zřetězen'''í - synonyma (položky s kolizemi) se ukládají do volných míst&lt;br /&gt;
&lt;br /&gt;
'''Vnější zřetězení''' - synonyma se ukládají do seznamů pod klíči&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Otevřené rozptýlení - hash funkce ==&lt;br /&gt;
&lt;br /&gt;
Kolize:&lt;br /&gt;
&lt;br /&gt;
1) nedefinované chování při kolizi - nutno dodefinovat&lt;br /&gt;
&lt;br /&gt;
2) lineární posun - při kolizi vkládáme na první volné místo lineárně (na indexech 1,2,3,4 od původní polohy&lt;br /&gt;
&lt;br /&gt;
3) kvadratický posun - při kolizi hledáme první volné místo na indexech podle kvadratické funkce (vzdálenosti 1, 4, 9, 16...)&lt;br /&gt;
&lt;br /&gt;
4) opakovaný hash - hashovací fci použijeme víckrát pokud dojde ke kolizi&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Uzavřené rozptýlení - přímé adresování ==&lt;br /&gt;
&lt;br /&gt;
metody 2) a 3) nejsou vhodné, vzniká shlukování (clustering), proto je dobré použít způsob 4) nebo lepší hash funkci&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tabulky s uzavřeným rozptýlením a vnějším zřetězením ==&lt;br /&gt;
&lt;br /&gt;
= kombinace obou&lt;br /&gt;
&lt;br /&gt;
- adresujeme přímo, při kolizi si ale do tabulky na konec uložíme, kam budeme vnitžně zřetězovat. Hash funkce tedy může být při kolizi (třeba náhodná), nebo tabulku rozdělíme na 2 části, jednu pro vyhledávání klíčů, a druhou pro ukládání synonym. ta už může být dynamicky alokovaná.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Metoda rozptýlených indexů ==&lt;br /&gt;
&lt;br /&gt;
To co bylo v předchozím případě v tabulce vyjmeme, a vytvoříme vedle. Uděláme si mapu synonym (synonyma v seznamu pro každý klíč) a tyto pak ukazují na index do pole.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Vyhledávání ==&lt;br /&gt;
&lt;br /&gt;
Má samozřejmě smysl jen pokud nemáme orákulum (= hashovací fci). Pokud orákulum máme, není třeba hledat protože ideální orákulum vždy ví, kam se podívat pro správná data  (The all-knowing Oracle is never surprised. How can she be, she knows everything. -- The Matrix: Revolution), reálné ví aspoň kde hledat.&lt;br /&gt;
&lt;br /&gt;
Jelikož je při přímém adresování orákulum pouhý index do tabulky (mno, to moc orákulum není, orákulum vždy ví, kam jít, aby nebyla kolize), alespoň nám napoví odkud hledat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Sekvenční:'''&lt;br /&gt;
&lt;br /&gt;
Hledáme klíč lineárně, pokud na něj narazíme, vrátíme hodnotu&lt;br /&gt;
&lt;br /&gt;
+ snadná implementace&lt;br /&gt;
&lt;br /&gt;
+ tabulka nemusí být uspořádaná&lt;br /&gt;
&lt;br /&gt;
- pomalé hledání&lt;br /&gt;
&lt;br /&gt;
'''Binární'''&lt;br /&gt;
&lt;br /&gt;
Jako sekvenční, ale klíče musí být seřazeny, a nad nimi vytvoříme BVS, tedy hledáme vždy v půlce intervalu&lt;br /&gt;
&lt;br /&gt;
+ rychlejší (O(log n))&lt;br /&gt;
&lt;br /&gt;
- nutnost udržovat tabulku seřazenou&lt;br /&gt;
&lt;br /&gt;
'''Fibonacciho'''&lt;br /&gt;
&lt;br /&gt;
Jako binární, ale nerozdělujeme  v polovině, ale podle Fibonacciho posloupnosti (tedy ne 1:1 -&amp;gt; 1:(1:1) -&amp;gt; 1:((1:1): 1) ale (1:1) -&amp;gt; (1:(1:2)) - &amp;gt; (1:((2:3):2))&lt;br /&gt;
&lt;br /&gt;
Prvky vybíráme jako dvojice, první z dvojice je ve Fibonacciho posloupnosti na pozici odpovídající úrovni vnožení stromu (výška větve, ve které hledáme)&lt;br /&gt;
&lt;br /&gt;
Fibonacciho ppst: a1 = 1, a2 = 1, ai = ai-1 + ai - 2 , tedy 1,1,2,3,5,8,13,21,34,55, ....&lt;br /&gt;
&lt;br /&gt;
'''Podle sekundárního klíče'''&lt;br /&gt;
&lt;br /&gt;
Jen pouze pokud sekundární klíč existuje v datech, např seznam jmen, jméno je primární (není, ale pro vysvětlení řekněme, že je) a rok je sekundární. Vyhledáme jména v sekundárním klíči a v nich pak hledáme jméno podle primárního klíče.&lt;br /&gt;
&lt;br /&gt;
Sekundární klíče máme v seznamu, který obsahuje seznam primárních klíčů zabulky pro každý sekundární klíč&lt;/div&gt;</summary>
		<author><name>81.201.60.245</name></author>	</entry>

	<entry>
		<id>https://www.512.cz/index.php?title=%C3%9Avod_do_technologie_programov%C3%A1n%C3%AD_a_programovac%C3%ADch_styl%C5%AF,_objektov%C4%9B_orientovan%C3%BD_n%C3%A1vrh,_z%C3%A1kladn%C3%AD_UML_diagramy,_psan%C3%AD_program%C5%AF_v_Jav%C4%9B</id>
		<title>Úvod do technologie programování a programovacích stylů, objektově orientovaný návrh, základní UML diagramy, psaní programů v Javě</title>
		<link rel="alternate" type="text/html" href="https://www.512.cz/index.php?title=%C3%9Avod_do_technologie_programov%C3%A1n%C3%AD_a_programovac%C3%ADch_styl%C5%AF,_objektov%C4%9B_orientovan%C3%BD_n%C3%A1vrh,_z%C3%A1kladn%C3%AD_UML_diagramy,_psan%C3%AD_program%C5%AF_v_Jav%C4%9B"/>
				<updated>2012-06-01T13:54:18Z</updated>
		
		<summary type="html">&lt;p&gt;81.201.60.245: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Úvod ==&lt;br /&gt;
Programování je proces vytváření software splňující určité funkce. K programování využíváme programovací jazyky, dříve procedurální (nestrukturované (asembler) - bez podprogramů, pouze skoky v programu (goto), nebo strukturované (basic, c, pascal) - podprogramy, skoky jen velmi vyjímečně), dnes nejčastěji objektově zaměřené (objekty jsou stavební kameny a obalují funkce, využití technik OOP).&lt;br /&gt;
&lt;br /&gt;
Dříve bylo programování spojeno s testováním, nyní je proces rozdělen do několika fází:&lt;br /&gt;
&lt;br /&gt;
'''Analýza''' - Sbírání informací od zákzníka či zadavatele&lt;br /&gt;
&lt;br /&gt;
'''Návrh''' - Návrh SW tak, aby splňoval požadavky analýzy&lt;br /&gt;
&lt;br /&gt;
'''Kódování''' - Implementace návrhu&lt;br /&gt;
&lt;br /&gt;
'''Ladění''' - Testování a odstraňování chyb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Styly ==&lt;br /&gt;
&lt;br /&gt;
'''Vodopád''' - fáze jdou za sebou, nevracíme se, ani neodbočujeme (nejstarší), týmy se zapojují do procesu pokud je na řadě jejich blok&lt;br /&gt;
&lt;br /&gt;
'''Formální''' - návrh je matematicky zcela do detailu popsán a jednotlivé bloky modelu jsou poté 1:1 implementovány&lt;br /&gt;
&lt;br /&gt;
'''Evoluční''' - začíná se malým funkčním SW, na který nabalujeme další funkce, ale nevíme, jaké funkce bude v budoucnu mít&lt;br /&gt;
&lt;br /&gt;
'''Iterativní''' - proces je rozdělen na iterace, v každé iteraci je naplánováno několik funkčností, iterace stejně dlouhé, po iteraci je SW vždy v kompletní spustitelné podobě&lt;br /&gt;
&lt;br /&gt;
'''Komponentový''' - využití hotových komponent, či implementace vlastních, po té stavění SW z komponent jako z kostek&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Objektově orientovaný návrh ==&lt;br /&gt;
&lt;br /&gt;
OO umožňuje, a klade si za cíle:&lt;br /&gt;
&lt;br /&gt;
'''Znovupoužitelnost''' - abstraktní části kódu jsou univerzální a je tedy možné je používat stále dokola&lt;br /&gt;
&lt;br /&gt;
'''Robustnost''' - návrh předpokládá všechny vstup, nejen ty, které jsou očekávané&lt;br /&gt;
&lt;br /&gt;
'''Přispůsobivost''' - návrh lze pouze s minimálními zásahy do kódu použít na různých platformách&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Pilíře OO návrhu ==&lt;br /&gt;
&lt;br /&gt;
'''Dědičnost, Zapouzdření, Polymorfysmus''' - PPA2&lt;br /&gt;
&lt;br /&gt;
'''Modularita''' - rozdělení programu na bloky - moduly&lt;br /&gt;
&lt;br /&gt;
'''Abstrakce''' - Návrh na abstraktní úrovni je snadno implementovatelný&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Jazyk UML ==&lt;br /&gt;
&lt;br /&gt;
Jazyk pro abstraktní návrh OO SW, modelování SW před implementací, navrhujeme pouze strukturu, nikoliv funkčnost.&lt;br /&gt;
Typy UML:&lt;br /&gt;
&lt;br /&gt;
'''diagram tříd a objektů''' - popisují statickou strukturu systému&lt;br /&gt;
&lt;br /&gt;
'''modely jednání (diagram případů užití)''' - dokumentují možné případy použití systému, události, na které musí systém reagovat&lt;br /&gt;
&lt;br /&gt;
'''scénáře činností (diagramy posloupností)''' - popisují scénář průběhu určité činnosti, těchto činností je model jednání složen&lt;br /&gt;
&lt;br /&gt;
'''diagramy spolupráce''' - zachycují komunikaci spolupracujících objektů&lt;br /&gt;
&lt;br /&gt;
'''stavové diagramy''' - popisují dynamické chování objektu nebo systému&lt;br /&gt;
&lt;br /&gt;
'''diagramy aktivit''' - průběh aktivit procesu nebo činností&lt;br /&gt;
&lt;br /&gt;
'''diagramy komponent''' - popisují rozdělení systému na funkční celky a definují náplň jednotlivých komponent&lt;br /&gt;
&lt;br /&gt;
'''diagramy nasazení''' - popisují umístění funkčních celků&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pro návrh diagramu tříd máme následující parametry:&lt;br /&gt;
&lt;br /&gt;
Atributy a metody - definujeme viditelnost a vlastnosti (+ public, # protected, - private, / readonly, in/out směr)&lt;br /&gt;
&lt;br /&gt;
Třída: obdélník, název tučně, pak seznam atributá a metod&lt;br /&gt;
&lt;br /&gt;
Objekt: Název:Třída&lt;br /&gt;
&lt;br /&gt;
Dědičnost - šipka od potomka k rodiči, může být i vícenásobná&lt;br /&gt;
&lt;br /&gt;
Asociace - 0..1  1..1 0..N 1...N  --&amp;gt; šipka od první třídy a ta obsahuje odkazy/využívá x..y objektů druhé třídy (např Podvozek 1 ---&amp;gt; 4 Kola ), nad šipkou název činnosti (pokud možno lepší než &amp;quot;má&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Kompozice - je li objekt v kompozici s jiným, je na něj silně vázán (například seznam a položka seznamu. seznam může existovat i bez položek, ale položka bez seznamu ne), značka prázdný kosočtverec&lt;br /&gt;
&lt;br /&gt;
Agregace  - volná vazba, abstrakce &amp;quot;používá&amp;quot;, objekty však mohou fungovat i nezávisle na sobě (například počítače v síti), značka plný kosočtverec&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Java ==&lt;br /&gt;
&lt;br /&gt;
'''Návrh''' - UML diagramy, CRC karty (karty, kde je pro každá blok sloupec Má za úkol a Vyžaduje). Je li toho na kartě příliš, je vhodné zvážit její rozdělení&lt;br /&gt;
&lt;br /&gt;
'''Implementace''' - podle návrhu, karta odpovídá třídě. &lt;br /&gt;
&lt;br /&gt;
'''Ladění  a testování''' - kontrolní výpisy, logování, watch na proměnných, ..., po té test pro různá data (generovaná, &amp;quot;nepříjemná&amp;quot;)  a sledování správnosti, rychlosti, využití zdrojů, uvolnění&lt;br /&gt;
&lt;br /&gt;
'''Dokumentace''' - štábní kultura, konvence pojmenovávání, komentáře, Javadoc komentáře a generovaná dokumentace&lt;/div&gt;</summary>
		<author><name>81.201.60.245</name></author>	</entry>

	</feed>