3.8.1 · D3 · Coding › String Algorithms › Naive pattern matching — O(nm)
Intuition Ye page kis liye hai
Parent note ne tumhe machine sikhaya tha: pattern slide karo, spell out karo, comparisons gino. Ye page us machine ko har tarah ke input par chalata hai — normal matches, no matches, overlaps, empty pattern, whole-text pattern, worst case, ek real-world search, aur ek exam trap. Agar tum in sab ko predict kar sako, toh test mein kuch bhi surprise nahi karega.
Shuru karne se pehle, ek reminder un vocabulary ka jo hum har jagah reuse karenge (sab parent mein defined hain):
==T == = text , length ==n ==. Likha jata hai T [ 0 ] , T [ 1 ] , … , T [ n − 1 ] (0-indexed).
==P == = pattern , length ==m ==, jahan m ≤ n .
==shift s == = ek candidate starting position; valid hota hai jab T [ s … s + m − 1 ] = P .
comparison = ek single "kya T [ s + j ] equal hai P [ j ] se?" test. Hum kaam measure karne ke liye inhe lete hain.
Naive matching ke har input ko inhi case classes mein se kisi ek mein rakha ja sakta hai. Har row ek alag cheez hai jo galat ho sakti hai ya specially behave karti hai, aur har ek ka ek worked example neeche diya gaya hai.
#
Case class
Isme kya khaas hai
Example
A
Single clean match
pattern exactly ek baar appear karta hai
Ex 1
B
No match at all
answer empty set hai
Ex 2
C
Overlapping matches
matches jinke ranges characters share karte hain
Ex 3
D
Worst case Θ ( nm )
har shift fail hone se pehle poora m pay karta hai
Ex 4
E
Best/lucky case ∼ O ( n )
almost har shift char 0 par hi mar jata hai
Ex 5
F
Degenerate: m = 1
pattern ek single character hai
Ex 6
G
Degenerate: m = n
pattern poore text ki length ka hai
Ex 7
H
Degenerate: empty pattern m = 0
formula ki limiting boundary
Ex 8
I
Real-world word problem
DNA / search feature
Ex 9
J
Exam twist: comparisons exactly gino
"kahan" nahi balki "kitna kaam"
Ex 10
Hum har cell cover karenge.
T = "HELLOWORLD", P = "WORLD". Saare valid shifts dhundho.
Forecast: "WORLD" kahan baithta hai, aur woh ek shift s kya hai? Padhne se pehle guess karo.
Setup. n = 10 , m = 5 , toh shifts run karte hain s = 0 … n − m = 5 .
Letters ko unke indices ke saath list karo.
H(0) E(1) L(2) L(3) O(4) W(5) O(6) R(7) L(8) D(9).
Ye step kyun? Naive matching index arithmetic hai; indices likhne se s + j concrete ho jaata hai, abstract nahi rehta.
s = 0 try karo: P [ 0 ] = W ko T [ 0 ] = H se compare karo. Mismatch → immediately break.
Ye step kyun? Early break (parent §HOW) ka matlab hai hum yahan sirf 1 comparison kharcha karte hain.
Shifts s = 1 , 2 , 3 , 4 sab E,L,L,O se shuru hote hain W ke against → har ek j = 0 par mismatch karta hai. 1 comparison each.
Ye step kyun? Jab tak match nahi milta, P [ 0 ] = W ke neeche wala letter hi matter karta hai; pattern ka pehla letter ek sasta filter hai.
s = 5 try karo: W=W, O=O, R=R, L=L, D=D. Sab 5 match, inner loop j = m = 5 tak pahunchta hai → match at s = 5 report karo .
Ye step kyun? j == m parent ka exact success test hai.
Answer: sirf s = 5 par match.
Verify: T [ 5 … 9 ] = WORLD = P . ✅ Aur s = 5 ≤ n − m = 5 , toh ye range mein hai.
T = "ABCDEF", P = "XYZ". Saare valid shifts dhundho.
Forecast: pattern ke text ke saath koi letters common nahi hain. Total kitne comparisons honge?
Setup. n = 6 , m = 3 , shifts s = 0 … 3 (yani n − m + 1 = 4 shifts).
Har shift pehle P [ 0 ] = X compare karta hai. X kabhi ABCDEF mein appear nahi karta, toh har shift j = 0 par mismatch karta hai.
Ye step kyun? Jab P [ 0 ] T mein absent ho, naive matching minimum possible kaam karta hai: har shift par ek comparison.
Comparisons gino: 4 shifts × 1 = 4 comparisons, zero matches.
Ye step kyun? Dikhata hai ki "no match" same nahi hai "worst case" ke — ek empty answer sasta ho sakta hai.
Answer: koi valid shifts nahi (empty set).
Verify: T [ 0..2 ] , T [ 1..3 ] , T [ 2..4 ] , T [ 3..5 ] mein se koi bhi XYZ ke equal nahi — sahi hai, aur algorithm kuch report nahi karta. ✅
T = "AAAA", P = "AA". Saare valid shifts dhundho. Note karo ki matches overlap kar sakte hain.
Forecast: AA kitni baar AAAA mein fit hota hai? Dhyan se — kya ye 2 hai ya 3?
Setup. n = 4 , m = 2 , shifts s = 0 … 2 , toh n − m + 1 = 3 candidates.
s = 0 : A=A, A=A → match. T [ 0 ] , T [ 1 ] use karta hai.
s = 1 : A=A, A=A → match. T [ 1 ] , T [ 2 ] use karta hai — pichle match ke saath T [ 1 ] share karta hai.
Ye step kyun? Naive matching har valid start report karta hai, overlapping wale bhi. Ye characters ko ek greedy scanner ki tarah "consume" nahi karta.
s = 2 : A=A, A=A → match. T [ 2 ] , T [ 3 ] use karta hai.
Answer: s = 0 , 1 , 2 par matches — teen overlapping matches.
Verify: matches ki count = n − m + 1 = 4 − 2 + 1 = 3 , jo maximum possible hai (har shift valid hai). ✅ Overlap expected hai kyunki same character ek match ka tail aur agle ka head ho sakta hai.
T = "AAAAAAAA" (n = 8 ), P = "AAAB" (m = 4 ). Total comparisons ki count karo.
Forecast: har shift par kitna kaam? Total guess karo.
Setup. shifts s = 0 … n − m = 4 , toh n − m + 1 = 5 shifts.
Har shift A,A,A match karta hai phir B par fail karta hai. T mein koi B nahi, toh P [ 3 ] = B hamesha mismatch karta hai — lekin sirf 3 successful comparisons ke baad .
Ye step kyun? Ye exactly parent ke worst-case box ka pattern hai: early break kabhi jaldi trigger nahi hota , toh hum hamesha poora m pay karte hain.
Comparisons per shift = m = 4 (teen matches + ek failing compare).
Ye step kyun? Failing compare tab bhi ek comparison count hota hai — tumhe dekhna pada tha jaanne ke liye ki fail hua.
Total = ( n − m + 1 ) ⋅ m = 5 × 4 = 20 comparisons, zero matches.
Ye step kyun? Ye Θ (( n − m + 1 ) m ) bound ko equality ke saath realize karta hai — is input par algorithm isse better nahi kar sakta.
Answer: 20 comparisons, koi match nahi.
Verify: formula ( n − m + 1 ) m = ( 8 − 4 + 1 ) ⋅ 4 = 5 ⋅ 4 = 20 . ✅ Look-alike prefix AAA hi maximum kaam force karta hai — yahi woh input hai jise beat karne ke liye KMP banaya gaya tha.
Dono extremes ko side by side dekho:
T = "XXXXXXXXA" (n = 9 ), P = "AB" (m = 2 ). Comparisons gino.
Forecast: pattern ka pehla letter A hai, jo T mein rare hai. Kya ye sasta hoga ya mehenga?
Setup. shifts s = 0 … 7 , yani n − m + 1 = 8 shifts.
Shifts s = 0 … 6 : har ek X vs P [ 0 ] = A se shuru hota hai → j = 0 par mismatch. 1 comparison each = 7 comparisons.
Ye step kyun? Jab P [ 0 ] T mein uncommon ho, early break almost har baar pehle character par hi fire karta hai — yahi wajah hai ki naive matching usually English text par fast hota hai.
Shift s = 7 : T [ 7 ] = X vs A → 1 comparison, mismatch. (8th shift, phir bhi 1 comparison.)
Ye step kyun? Aakhri shift bhi jaldi mar jaata hai — index 8 par akela A ke liye s = 8 chahiye, lekin s = 8 > n − m = 7 , toh ye kabhi poora match start hi nahi karta.
Total = 8 × 1 = 8 comparisons , koi match nahi.
Ye step kyun? Ex 4 se compare karo: same idea (no match), bilkul alag cost . Kaam ≈ n hai, nm nahi.
Answer: 8 comparisons, koi match nahi — O ( n ) jaisa behave karta hai.
Verify: 8 = n − m + 1 = 9 − 2 + 1 . Har shift ne exactly 1 comparison kiya, toh total = number of shifts. ✅
T = "BANANA", P = "A". Saare valid shifts dhundho.
Forecast: m = 1 ke saath, inner loop trivial hai. Algorithm kis cheez mein reduce ho jaata hai?
Setup. n = 6 , m = 1 , shifts s = 0 … 5 , toh n − m + 1 = 6 candidates — T ka har index.
Inner loop ki length 1 hai: ye sirf poochta hai "kya T [ s ] = A?". Koi looping nahi, ek comparison per shift.
Ye step kyun? Jab m = 1 hota hai toh algorithm ek plain linear scan mein degenerate ho jaata hai — "ek character ke har occurrence ko dhundho."
Indices walk karo: B(0) A(1) N(2) A(3) N(4) A(5). A s = 1 , 3 , 5 par hai.
Ye step kyun? Confirm karta hai ki degenerate case ab bhi same j == m test use karta hai (yahan j == 1 ).
Answer: s = 1 , 3 , 5 par matches.
Verify: total comparisons = 6 = n (har position par ek), jo single-char scan ke O ( n ) cost se match karta hai. ✅
T = "CODE", P = "CODE" (m = n = 4 ). Phir P = "COVE". Dono ke liye valid shifts dhundho.
Forecast: m = n ke saath try karne ke liye sirf ek jagah hai. Kitne shifts?
Setup. n − m + 1 = 4 − 4 + 1 = 1 , toh sirf ek candidate hai s = 0 .
Case P="CODE": C=C, O=O, D=D, E=E compare karo → sab match → s = 0 report karo .
Ye step kyun? Jab m = n hota hai, naive matching sirf poori string ka equality test hai.
Case P="COVE": C=C, O=O, D≠V → j = 2 par break, koi match nahi.
Ye step kyun? Full-length pattern ko bhi early break milta hai; ek galat letter se khatam ho jaata hai.
Answer: "CODE" → s = 0 par match; "COVE" → koi match nahi.
Verify: s = 0 hi sirf shift hai kyunki n − m + 1 = 1 . CODE= CODE ✅; CODE = COVE ✅.
T = "HI" (n = 2 ), P = "" (empty, m = 0 ). Formula kya predict karta hai, aur kya ye sensible hai?
Forecast: n − m + 1 kitne shifts deta hai? Kya ek empty pattern "match" karta hai kahin bhi?
Setup. Count mein plug karo: n − m + 1 = 2 − 0 + 1 = 3 candidate shifts: s = 0 , 1 , 2 .
Inner loop while j < m kabhi run nahi karta kyunki m = 0 : condition j < 0 false hai j = 0 par.
Ye step kyun? Zero characters compare karne ke saath, loop j = 0 = m ke saath instantly finish ho jaata hai, toh success test j == m pass ho jaata hai .
Isliye har shift s = 0 , 1 , 2 "valid" hai.
Ye step kyun? Ye standard convention hai: empty string har position par substring hai, end position s = n par bhi. Yahi wajah hai ki count n + 1 hai, n nahi.
Answer: s = 0 , 1 , 2 par 3 matches — empty pattern har position par occur karta hai (aur bilkul end par bhi).
Verify: n − m + 1 = 2 − 0 + 1 = 3 , aur s = n = 2 ek legal empty-match position hai. Formula boundary m = 0 par consistent rehta hai. ✅
m = 0 ka trap
Bahut saare hand-written loops for s in range(n - m) likhte hain (+1 missing) ya assume karte hain "empty pattern → no matches." Dono galat hain: correct count ==n − m + 1 == hai aur ye n + 1 empty matches deta hai jab m = 0 ho. Hamesha m = 0 aur m = n ko boundary cases ke roop mein test karo.
Ek gene scanner ek DNA strand T = "GATTACAGATTACA" (n = 14 ) padhta hai aur motif P = "GATTACA" (m = 7 ) dhundta hai. Saare start positions report karo.
Forecast: text pattern ki repeat jaisi lagti hai. Kitne matches hain, aur kya wo overlap karte hain?
Setup. shifts s = 0 … n − m = 7 , toh n − m + 1 = 8 candidates.
Strand ko index karo: G0 A1 T2 T3 A4 C5 A6 G7 A8 T9 T10 A11 C12 A13.
Ye step kyun? Motif finding exactly pattern-matching problem hai; indexing biology ko arithmetic bana deta hai.
s = 0 : GATTACA vs T [ 0..6 ] = GATTACA → 7 matches → s = 0 report karo .
s = 1 … 6 : har ek A,T,T,A,C,A se shuru hota hai P [ 0 ] = G ke against → j = 0 par mismatch, 1 comparison each.
Ye step kyun? G sirf indices 0 aur 7 par appear karta hai, toh first-letter filter zyaadatar shifts ko instantly khatam kar deta hai.
s = 7 : GATTACA vs T [ 7..13 ] = GATTACA → 7 matches → s = 7 report karo .
Ye step kyun? Dono matches yahan overlap nahi karte (0 + 7 = 7 ), Ex 3 ke unlike.
Answer: motif s = 0 aur s = 7 par start hota hai.
Verify: T [ 0..6 ] = T [ 7..13 ] = GATTACA. Do matches, 7 = m apart, toh back-to-back, koi overlap nahi. ✅
T = "ABABAB" (n = 6 ), P = "ABA" (m = 3 ). Exam question: (a) saare matches do aur (b) algorithm jo exact character comparisons karta hai unki count karo, early break use karte hue.
Forecast: yahan matches overlap karte hain. Kaun se shifts poora kaam karte hain, kaun jaldi mar jaate hain?
Setup. shifts s = 0 … 3 . T ko index karo: A0 B1 A2 B3 A4 B5.
s = 0 : A=A, B=B, A=A → match . 3 comparisons.
s = 1 : P [ 0 ] = A vs T [ 1 ] = B → mismatch. 1 comparison.
Ye step kyun? Har odd shift B par start hota hai, early break se immediately khatam.
s = 2 : A=A, B=B, A=A → match . 3 comparisons.
s = 3 : P [ 0 ] = A vs T [ 3 ] = B → mismatch. 1 comparison.
Ye step kyun? Jodte hain toh exam ka number milta hai, aur full-work aur early-break shifts ka mix dikhata hai.
Total comparisons = 3 + 1 + 3 + 1 = 8 .
Ye step kyun? Crude upper bound ( n − m + 1 ) m = 4 × 3 = 12 se compare karo: early break ne 12 − 8 = 4 comparisons bachaaye.
Answer: (a) s = 0 , 2 par matches; (b) exactly 8 comparisons (bound 12 tha).
Verify: matches T [ 0..2 ] = T [ 2..4 ] = ABA ✅. Comparisons 8 ≤ 12 = ( n − m + 1 ) m ✅ — actual kaam worst-case ceiling se neeche hai kyunki do shifts ne jaldi break kiya.
Recall Tumhare liye kaunsa cell sabse mushkil tha?
Answers reveal karo inhe lock karne ke liye.
Ex 3 vs Ex 9 — kya matches overlap karte hain? ::: Ex 3 overlap karta hai (s = 0 , 1 , 2 letters share karte hain); Ex 9 nahi karta (s = 0 , 7 exactly m apart hain).
Ex 4 vs Ex 5 — dono ka koi match nahi tha; cost alag kyun? ::: Ex 4 ka pattern prefix AAA text se match karta hai toh break kabhi jaldi fire nahi hota (Θ ( nm ) ); Ex 5 ka pehla letter A rare hai toh har shift char 0 par mar jaata hai (O ( n ) ).
Length n ke text ke liye kitne empty-pattern matches? ::: n + 1 (har position 0 … n par ek), n − m + 1 se m = 0 ke saath.
Naive pattern matching — O(nm) — wo parent jiske algorithm ko humne har case par exercise kiya.
KMP Algorithm — Ex 4 ke worst case ko matched info reuse karke beat karta hai.
Boyer-Moore Algorithm — Ex 5-style cases ko aur bhi zyaada beat karta hai aage skip karke.
Rabin-Karp Algorithm — char-by-char ki jagah hashing se poori windows compare karta hai.
Big-O Notation — "Θ ( nm ) worst, O ( n ) lucky" ki language.
Sliding Window Technique — har example ke peeche "pattern slide karo" ka motion.
Substring Search Problem — wo umbrella problem jise saare das examples instantiate karte hain.
Empty pattern n+1 matches Ex8