3.8.3 · D1 · Coding › String Algorithms › Rabin-Karp — rolling hash, O(n+m) expected
Rabin-Karp text ke har chunk ko ek single number ("fingerprint") mein badal deta hai, taaki do chunks ko compare karna sirf do numbers compare karna ho — instant. Isse puri long text mein fast banane ke liye, hum fingerprint aise banate hain ki window ko ek step slide karna sirf kuch arithmetic operations mein number update kar de — har baar har character dobara padhne ki zaroorat nahi.
Ye page assume karta hai ki tumne pehle kuch nahi dekha. Parent note mein use kiya gaya har letter, subscript, aur squiggle yahan unpack kiya gaya hai, ek aisi order mein jahan har idea sirf pehle wale ideas pe depend karta hai.
Ek string bas characters ki ek ordered row hai — letters, digits, symbols — jo left se right rakhe hote hain. Hum ise s likhte hain.
Ek string ko boxes ki row ki tarah socho, jisme har box ek character rakhta hai:
Parent note mein s 0 , s 1 , … , s m − 1 jaisi cheezein likhi hain. Exactly yahi matlab hai unka:
Definition Index aur subscript notation
s 0 , s 1 , …
Letter ke neeche wala chhota number ek index hai — character ki position , 0 se count karte hue. Toh s 0 pehla box hai, s 1 doosra, aur aise hi aage. Positions zero se start hoti hain kyunki code mein arrays aise hi number hote hain.
Figure dekhо: red box s 0 hai, yaani sabse left wala character. Subscript literally hai "kaunsa box."
Definition Character code
Computers letter "a" directly store nahi kar sakte — woh uske liye ek number store karte hain. Woh number character ka code hai. Parent ke chhote example mein codes haath se choose kiye gaye hain: a = 0 , b = 1 . Real code mein tum built-in code use karte ho (jaise ASCII, jahan 'a' ka code 97 hai).
Ye topic ise kyun chahta hai: hum abhi ek poori string ko ek bada number treat karne wale hain. Iske liye, pehle har character ko ek number hona chahiye. Code woh pehla translation hai.
m aur n
n text T ki length hai (woh lamba haystack jisme hum search karte hain). m pattern P ki length hai (woh chhota needle jo hum dhundh rahe hain). "Length" ka matlab hai row mein kitne boxes hain.
Kyunki P mein m boxes hain, iski positions P [ 0 ] , P [ 1 ] , … , P [ m − 1 ] tak chalti hain — sabse bada index m − 1 hai, m nahi, kyunki hum 0 se count karna shuru kiya tha.
Ye topic ise kyun chahta hai: note mein har cost (O ( nm ) , O ( n + m ) ) m aur n ke terms mein likhi hai. Ye "kitna kaam" wale dials hain.
O ( ⋅ )
O ( something ) ek method ke steps ka rough count hai, sirf woh rakhte hain jo matter karta hai jab input bada ho. O ( m ) ka matlab hai "kaam m ke proportion mein badhta hai." O ( 1 ) ka matlab hai "steps ki ek fixed thaadi si sankhya, input chahe kitna bhi bada ho" — yahi woh prize hai jo hum chahte hain.
O ( nm ) vs O ( n + m ) ek picture mein
O ( nm ) ek rectangle hai: n windows, har ek ki cost m character-comparisons — area n × m . O ( n + m ) do chhoti strips hain jo end to end rakhi hain. n = 1000 , m = 100 ke liye, yeh 100 , 000 steps vs 1 , 100 hai. Yahi gap Rabin-Karp ka pura point hai.
Ye topic ise kyun chahta hai: poora selling point ek speed claim hai. Jaane bina ki O ( n + m ) ka matlab kya hai, "expected O ( n + m ) " sirf shor hai.
T [ i .. i + m − 1 ]
Ek window text ka ek slice hai jo exactly m characters wide hai — pattern jitni hi width. Notation T [ i .. i + m − 1 ] ka matlab hai "T ke characters position i se lekar i + m − 1 tak, including." Kyunki yeh i se start hoti hai aur m wide hai, yeh i + m − 1 par khatam hoti hai.
Sliding ka matlab hai: window ko ek box right mein move karo, toh i ban jata hai i + 1 . Sabse left wala character bahar chala jata hai; ek naya character right se enter karta hai.
Figure mein, red character woh hai jo slide karte waqt enter kar raha hai; left pe greyed wala leave kar raha hai. Yahi "ek jaata hai, ek aata hai" wali picture rolling update ko possible banati hai — sirf do characters change hote hain.
Ye topic ise kyun chahta hai: n − m + 1 possible windows hain (inhe 0 , 1 , … se start karo jab tak far edge text se bahar na chali jaye). Rabin-Karp har ek par ek baar visit karta hai.
Hashing se pehle, tumhe feel karna chahiye ki ordinary numbers kaise bante hain.
b aur place value
Hamare rozana ke base 10 mein, number "237" teen alag digits nahi hai — yeh hai
2 ⋅ 1 0 2 + 3 ⋅ 1 0 1 + 7 ⋅ 1 0 0 .
Har digit ko base b (yahan b = 10 ) ki ek power se multiply kiya jaata hai uski jagah ke hisaab se. Sabse left wala digit sabse bada weight carry karta hai.
Definition Exponent / power
b k
b k ka matlab hai "b ko khud se k baar multiply karo." b 0 = 1 hamesha (empty product). Toh 1 0 2 = 100 , 1 0 1 = 10 , 1 0 0 = 1 — hundreds, tens, aur ones places ke weights.
Intuition String ko base-
b number mein kyun convert karein?
Har character code ko ek "digit" maano aur ek base b chuno (parent b = 26 use karta hai). Tab string ek AKELA number ban jaati hai same place-value rule ke saath. Do alag strings almost hamesha alag numbers par land karti hain — toh woh number string ka fingerprint hai.
Ye topic ise kyun chahta hai: hash formula
H ( s ) = s 0 b m − 1 + s 1 b m − 2 + ⋯ + s m − 1 b 0
exactly "237" ka place-value formula hai, bas character codes digits ki jagah hain aur base b hai. Ise ordinary counting ki tarah pahchanna hi poora trick hai.
Upar wala fingerprint number ek lambi string ke liye bahut bada ho sakta hai. Hum ise remainder se kabu karte hain.
a mod q (modulo)
a mod q woh remainder hai jo a ko q se divide karne ke baad bachta hai. Example: 17 mod 5 = 2 , kyunki 17 = 3 ⋅ 5 + 2 . Result hamesha { 0 , 1 , … , q − 1 } mein hota hai.
Intuition Ghadi wali picture
Ek ghadi mod 12 arithmetic hai: 12 ke baad tum 0 par wapas aa jaate ho. Modulo q ek aisi ghadi hai jisme q marks hain. Chahe fingerprint kitna bhi bada ho jaaye, mod q lena use q marks mein se ek par fold kar deta hai — toh numbers chhote rehte hain aur computers unhe handle kar sakte hain.
q — ek large prime
q woh number hai jiske against hum remainder lete hain. Hum ise prime (sirf 1 aur khud se divisible) aur large (jaise 1 0 9 + 7 ) choose karte hain. Prime hona fingerprints ko ghadi par evenly spread karta hai, toh do alag strings rarely ek hi mark par land karti hain. Deeper "why prime" ke liye Modular Arithmetic dekhо.
Common mistake Code mein remainders negative kyun ja sakte hain
Jab hum roll ke dauran subtract karte hain, toh H i − T [ i ] ⋅ P high jaisi intermediate value 0 se neeche ja sakti hai. Ghadi par, − 3 mod 12 ko 9 hona chahiye, lekin bahut si languages − 3 return karti hain. Parent mein fix — ((x) % q + q) % q — use wapas ghadi ke face par le aata hai.
Ye topic ise kyun chahta hai: har hash ( mod q ) mein rehta hai. Prime q hi "probably different fingerprints" ko "provably rare collisions (~1/ q )" mein badalta hai. Link: Hashing , Birthday Paradox .
Ab parent ke formulas ke symbols sab earn ho chuke hain:
P high = b m − 1 mod q precompute kyun karein?
Har slide mein leaving character ka weight subtract karna padta hai, aur woh weight hamesha b m − 1 hota hai (sabse left wali place). Har step mein fresh b m − 1 compute karna extra kaam karega aur O ( 1 ) update ko barbad karega. Ise ek baar compute karo, hamesha ke liye reuse karo.
Ye topic ise kyun chahta hai: P high woh single precomputed constant hai jo roll ko sasta banata hai. Yeh boxed rolling formula mein aur "Drop, Slide, Add" mnemonic mein appear karta hai.
Ek collision tab hoti hai jab do alag strings ek hi fingerprint produce karti hain. Kyunki hum infinitely many strings ko sirf q ghadi ke marks par squash karte hain, kuch zaroor share karenge (pigeonhole). Ek accha large prime ise rare banata hai (~1/ q ), kabhi impossible nahi.
Intuition Hum phir bhi character-by-character verify kyun karte hain
Equal strings ke hashes hamesha equal hote hain — toh hashes ka mismatch matlab "definitely equal nahi," jo hum trust karke instantly skip kar sakte hain. Lekin equal hashes ka matlab sirf "probably equal" hota hai. Toh hash hit par hum ek O ( m ) check karte hain actual characters confirm karne ke liye. Hash ek filter hai, proof nahi .
Ye topic ise kyun chahta hai: isliye algorithm expected O ( n + m ) hai, guaranteed nahi — rare collisions kabhi kabhi verification force karti hain. Collisions actually kitni likely hain iska intuition ke liye Birthday Paradox dekhо.
Index and subscript s0 s1
Precomputed b to m minus 1
s 2 mein subscript tumhe kya batata hai?Character ki position, 0 se count karte hue — toh s 2 teesra box hai.
n aur m kya hain?n = text T ki length; m = pattern P ki length.
O ( 1 ) ka matlab kya hai?Input size se independent, steps ki ek fixed sankhya — constant time.
"504" ko base-10 place-value form mein likhо. 5 ⋅ 1 0 2 + 0 ⋅ 1 0 1 + 4 ⋅ 1 0 0 .
Kisi bhi base b ke liye b 0 kya hai? 1 .
17 mod 5 kya hai?2 (kyunki 17 = 3 ⋅ 5 + 2 ).
q prime aur large kyun choose karte hain?Fingerprints evenly spread karne ke liye aur collisions rare banane ke liye (~1/ q ).
Code mein modular result negative kyun ja sakta hai, aur fix kya hai? Subtraction 0 se neeche ja sakti hai; fix hai ((x) % q + q) % q.
Length n ke text mein width m ki kitni windows exist karti hain? n − m + 1 .
Collision kya hai, aur hum panic kyun nahi karte? Do alag strings ek hash share karti hain; hum ise har hash hit par ek O ( m ) character verification se pakad lete hain.
b m − 1 mod q precompute kyun karein?Yeh leaving character ka weight hai, har slide mein chahiye; ise ek baar compute karna roll ko O ( 1 ) rakhta hai.
Hashing — polynomial/modular fingerprint idea puri tarah se
Modular Arithmetic — ghadi, remainders, aur q prime kyun hai
Birthday Paradox — collisions actually kitni likely hain
String Hashing for Substring Comparison — wahi rolling hash range equality ke liye reuse kiya gaya
Knuth-Morris-Pratt — ek collision-free linear matcher (contrast)
Z-Algorithm — ek aur linear pattern matcher (contrast)