PREFIKS FUNKSIYASI, UNI HISOBLASH VA QO’LASH. KNUT-MORISS-PRATT ALGORITMI
PREFIKS FUNKSIYASI, UNI HISOBLASH VA QO’LASH. KNUT-MORISS-PRATT ALGORITMI MUNDARIJA KIRISH……………………………………………………………………..….3 I-BOB. PREFIKS FUNKSIYASI, UNI HISOBLASH VA QO’LASH ……4 1.1.Prefiks funksiyasiga ta’rif va Prefiks funksiyasi………………….......4 1.2. Prefiks funktsiyasidan foydalanishga misol…………………………..6 1.3. Prefiks funktsiyasini qo’llanilishi……………………………………..11 I I -BOB. KNUT-MORISS-PRATT ALGORITMI…………………………19 2.1. Knut-Morris-Pratt algoritmi………… ………………………………...19 XULOSA……………………………………………………………..…...….33 FOYDALANILGAN ADABIYOTLAR……………………………….…..34 1
KIRISH Informatika sohasida Knuth-Morris-Pratt string-qidiruv algoritmi (yoki KMP algoritmi) mos kelmaslik yuzaga kelganda so'zning o'zini o'zida mujassamlashtirganini kuzatish orqali asosiy "matn qatori" S ichida "so'z" W ning paydo bo'lishini qidiradi. keyingi o'yin qaerda boshlanishi mumkinligini aniqlash uchun etarli ma'lumot, shu bilan avval mos keladigan belgilarni qayta tekshirishni chetlab o'tadi. Algoritm Jeyms X. Morris tomonidan ishlab chiqilgan va mustaqil ravishda Donald Knut tomonidan avtomatlar nazariyasidan "bir necha hafta o'tgach" kashf etilgan.[1][2] Morris va Vogan Pratt 1970 yilda texnik hisobotni chop etishdi.[3] 1977-yilda uchtasi algoritmni birgalikda nashr etishgan.[1] Mustaqil ravishda, 1969 yilda Matiyasevich[4][5] ikkilik alifboda satr-naqsh mos keladigan aniqlash masalasini o'rganayotganda ikki o'lchovli Tyuring mashinasi tomonidan kodlangan shunga o'xshash algoritmni kashf etdi. Bu satrlarni moslashtirish uchun birinchi chiziqli vaqt algoritmi edi. Algoritm 1970 yilda Donald Knut va Vogan Pratt tomonidan va mustaqil ravishda Jeyms X. Morris tomonidan ishlab chiqilgan. 1977 yilda uchtasi birgalikda nashr etishgan. KMP usuli izlanayotgan satrni oldindan qayta ishlashdan foydalanadi, ya’ni uning asosida prefiks funksiya yaratiladi. Bunda quyidagi g’oyadan foydalaniladi. Agar i uzulikdagi so’z prefiksi (u ham suffiks) bitta simvolga uzun bo’lsa, u holda bir vaqtda i-1 uzunlikdan qism satr prefiksi ham bo’ladi. Shunday qilib, biz oldingi qism satr prefiksini tekshiramiz. Agar u to’g’ri kelmasa, u holda uning prefiksining prefiksini tekshiramiz va hakozo. Shunday ish yuritib, eng katta izlanayotgan prefiksni topamiz. Navbatdagi savol: nima uchun prosedura ish vaqti chiziqli, unda ichki joylashgan sikl borku? Bizga undan prefiks-funksiyani berish m marta ro’y beradi, qolgan vaqtda k o’zgaruvchi o’zgaradi. while siklda u(P[k]<k) ga kamaygan, lekin noldan kichkina bo’lmagani uchun shunga qaraganda kam bo’lmagan marta kamayishi mumkin. K o’zgaruvchi birga m dan ko’p bo’lmagan marta o’sadi. Demak, k o’zgaruvchi jami ikki martadan ko’p bo’lmagan holda o’zgaradi. Bunday butun prosedura ish vaqti O( m) ga teng [7,8]. Haqiqiy dunyoda KMP algoritmi naqshlarni moslashtirish uzun satrlarda amalga oshiriladigan ilovalarda qo'llaniladi, ularning belgilari kichik alifbodan olingan. Tegishli misol - faqat 4 ta belgidan (A, C, G, T) iborat DNK alifbosi. s qatori uchun prefiks funktsiyasi s ning eng uzun to'g'ri prefiksi uzunligi sifatida aniqlanadi, bu ham s ning qo'shimchasi hisoblanadi. To'g'ri (men uni kursivlashni to'xtataman) prefiksi s ning o'zi bo'lmagan har qanday s prefiksi, ya'ni s ning har qanday prefiksidir. 2
I-BOB. PREFIKS FUNKTSIYASI, UNI HISOBLASH VA QO’LLANILISH 1.1.Prefiks funktsiyasi ta'rifi Sizga n uzunlikdagi s qator berilgan. Ushbu qator uchun prefiks funksiyasi n uzunlikdagi p massiv sifatida aniqlanadi, bu erda π[i] s[0…i] pastki satrining eng uzun tegishli prefiksining uzunligi, u ham ushbu pastki qatorning qo'shimchasi hisoblanadi. Satrning to'g'ri prefiksi qatorning o'ziga teng bo'lmagan prefiksdir. Ta rifi bo yicha π[0]=0. Prefiks funktsiyasining matematik ta'rifi quyidagichaʼ ʻ yozilishi mumkin: Masalan, "abcabcd" qatorining prefiks funksiyasi [0,0,0,1,2,3,0] va "aabaaab" qatorining prefiks funksiyasi [0,1,0,1,2,2,3 ]. Prefiks funktsiyasi s satrining prefiks funktsiyasi π massivga teng, bu erda π [i] s [0..i] satrning uning qo'shimchasiga mos keladigan maksimal prefiksi uzunligini bildiradi. Arzimas holatlar (prefiks qo'shimchaga teng va butun satrga teng) hisobga olinmaydi. 3
1-rasm. Rasmda uzunligi ushbu pozitsiyadagi prefiks funktsiyasi qiymatiga teng bo'lgan teng pastki qatorlar ko'rsatilgan. Butun “abacaba” qatori uchun prefiks funksiyasi: {0,0,1,0,1,2,3}. π [0] = π [1] = 0, chunki “a” va “ab” satrlari ahamiyatsiz va shuning uchun hisobga olinmaydi. Ba'zi hollarda prefiks va qo'shimchalar bir-biriga mos kelishi mumkin: 2-rasm. Prefiks funktsiyasini topish uchun sodda algoritm O (N 3 ) murakkabligiga ega, bu ko'p hollarda qabul qilinishi mumkin emas. Juda ham samarali O (N) algoritmi mavjud. Amalga oshirish: vector<int> prefix_function(const string& s) { vector<int> pi(s.length(), 0); for (int i = 1; i < s.length(); i++) { int j = pi[i - 1]; //biz davom ettirmoqchi bo'lgan prefiksning joriy uzunligi //s [0..j-1] = s [i-j..i-1] bo lishi kafolatlanadi.ʻ while (j > 0 && s[i] != s[j]) { //joriy prefiks bilan davom etgunimizcha j = pi[j - 1]; // uning uzunligini iloji boricha qisqartiring } //Endi j - biz davom ettirishimiz mumkin bo'lgan prefiksning maksimal uzunligi, 4
//yoki hech biri mavjud bo'lmasa 0. if (s[i] == s[j]) { pi[i] = j + 1; } else { //Bu faqat j = 0 uchun sodir bo'lishi mumkin pi[i] = j; } } return pi; } 1.2.Prefiks funktsiyasidan foydalanishga misollar Prefiks funktsiyasi juda kuchli tuzilma bo'lib, u satr muammolarining muhim qismini hal qilish uchun ishlatilishi mumkin. Prefiks funksiyasining klassik muammosi qatordagi pastki qatorni topish muammosidir (KMP algoritmi dastlab ushbu muammoni hal qilish uchun maxsus ishlab chiqilgan). Keling, buni misol sifatida ko'rib chiqaylik. Faraz qilaylik, s satrida t pastki qatorni topishimiz kerak. Prefiks funktsiyasi yordamida bu arzimas tarzda amalga oshiriladi: biz t + # + s qatoridan prefiks funktsiyasini topamiz (xesh hech qanday satrda ko'rinmasligi kafolatlangan belgini bildiradi). Agar ushbu prefiks funktsiyasi t uzunligiga teng qiymatlarni o'z ichiga olsa, u holda t s tarkibiga kiradi. Ya'ni, π [i] = | t | bo'lsin. Demak, s [i− | t | −1] t ning s ichida yuzaga kelishining oxirgi belgisidir. C ++ da qo’llanilish: #include <bits/stdc++.h> using namespace std; vector<int> prefix_function(const string& s) { vector<int> pi(s.length(), 0); for (int i = 1; i < s.length(); i++) { int j = pi[i - 1]; while (j > 0 && s[i] != s[j]) { j = pi[j - 1]; } 5