Кнут-Моррис-Праттын алгоритм
Википедиагийн чанарын стандартад нийцүүлэхийн тулд энэ өгүүллийг хянан тохиолдуулах хэрэгтэй байна. Энэ талаар хэлэлцүүлгийн хуудас дээр юм уу энэ тэмдгийг илүү нарийвчилсан тэмдгээр солино уу. |
Кнут-Моррис-Праттын алгоритм (Англи: Knuth–Morris–Pratt algorithm) нь тэмдэгт хайлтын алгоритмын төрөл.
Энэ алгоритм нь бүх боломжийг шалгах алгоритмын үед хийгдэж байсан х тэмдэгт мөрийн зүүнээс баруун тийш чиглэлтэй, нэг тэмдэгтийн алхамтай шилжилтүүдийн алхмыг уртасган, тоог багасгадаг.
n урттай y тэмдэгт мөрөөс m урттай х тэмдэгт мөрийг хайж байна гэж үзье. Тухайн тохиолдолд у тэмдэгт мөрийн j дэх тэмдэгтээс (0≤j<n) эхэлсэн дэд мөртэй х-г харьцуулж байхад х тэмдэгт мөрийн i дэх тэмдэгт нь (0≤i<m) зөрсөн байг. Энэ нь x[0..i-1] = y[j .. j+i-1] = u ба a = x[i] ≠ y[i+j]=b гэсэн үг юм.
Ингэж тэмдэгт зөрсний дараа х тэмдэгт мөрийн эхлэлийг шууд у тэмдэгт мөрийн j+i дугаар байрлалд аваачиж болохгүй. Учир нь х тэмдэгт мөрийг баруун тийш нэг нэг тэмдэгтээр шилжүүлэх үед х тэмдэгт мөрийн эхэнд байрлах ямар нэг v дэд тэмдэгт мөр u тэмдэгтийн төгсгөлийн хэсэгтэй таарч магадгүй. Ийм тохиолдлуудыг орхилгүй шалгахын тулд u тэмдэгт мөрийн хувьд төгсгөл хэсэгтэй нь таарах х тэмдэгт мөрийн эхлэлийн хамгийн урт дэд тэмдэгт мөрийг хил гэж нэрлэе. Мөн програмчлах үед энэ хилийн утгыг олж mpNext[i] элементэд хадгална.
Энэ тохиолдолд a ба b тэмдэгтүүд зөрсний дараа b тэмдэгтийг c=x[mpNext[i]] тэмдэгттэй харьцуулна гэсэн үг. Өөрөөр хэлбэр х тэмдэгт мөрийг strlen(u)-strlen(v) тооны тэмдэгтээр баруун тийш шилжүүлнэ.
Моррис-Праттын алгоритм дахь шилжилт (v нь u-гийн хил болно)
Алгоритмын бэлтгэл ажиллагаа болох mpNext хүснэгтийг байгуулах хугацаа O(m) ба ажиллах нийт хугацааг O(n+m) гэж үнэлж болно.
Жишээ:
void preMp(char * x, int m, int mpNext[]) {
int i, j;
i = 0;
j = mpNext[0] = -1;
while (i < m) {
while (j > -1 && x[i] != x[j])
j = mpNext[j];
mpNext[++i] = ++j;
}
}
void MP(char * x, int m, char * y, int n) {
int i, j, mpNext[XSIZE];
/* Preprocessing */
preMp(x, m, mpNext);
/* Searching */
i = j = 0;
while (j < n) {
while (i > -1 && x[i] != y[j])
i = mpNext[i];
i++;
j++;
if (i >= m) {
OUTPUT(j - i);
i = mpNext[i];
}
}
}