تابع پیشوند KMP
برای هر پیشوند الگو، طول بلندترین پیشوند سرهای را که پسوند آن هم هست حساب میکند؛ KMP با همین جدول بعد از ناهمخوانی میداند چقدر جلو برود.
مرز یک رشته، پیشوند سرهای است که پسوند آن هم هست (برای ababa: aba و a). π[q] طول بلندترین مرزِ P[0..q] است.
- زمان:
O(m) (amortized) - حافظه:
O(m) - CLRS، بخش ۳۲.۴
- هوروویتز–ساهنی، فصل ۲
الگوی ababaca؛ π = (0, 0, 1, 2, 3, 0, 1).
def prefix_function(P):# pi[q] = the length of the longest proper prefix of P[0..q] that is also a suffix of it.m = len(P)pi = [0] * mtable = [list(P), pi]k = 0for q in range(1, m):while k > 0 and P[k] != P[q]:k = pi[k - 1]if P[k] == P[q]:k = k + 1pi[q] = kreturn pi
شروع اجرا
جدول هنوز خالی است.
متغیرهای محلی
نارنجی = در همین گام عوض شد
Call stack
- prefix_function()خط 1
توضیح
ایده
مرز یک رشته، پیشوند سرهای است که پسوند آن هم هست (برای ababa: aba و a). π[q] طول بلندترین مرزِ P[0..q] است.
چرا مهم است؟
در KMP وقتی q نویسه از الگو جور شده و نویسهی بعدی نمیخواند، لازم نیست از اول شروع کنیم: بلندترین مرزِ قسمت جورشده دقیقاً همان مقداری است که هنوز معتبر است، پس به π[q − 1] برمیگردیم.
محاسبه
خود جدول هم با همین ایده ساخته میشود: اگر P[k] = P[q] باشد مرز یکی بلندتر میشود؛ وگرنه به مرزِ بعدیِ کوتاهتر π[k − 1] برمیگردیم و دوباره امتحان میکنیم.
هزینه
k در کل حداکثر m بار زیاد میشود و هر برگشت آن را کم میکند؛ پس کل کار O(m) است (تحلیل سرشکن).
در trace به چه چیزی نگاه کنی
- اشارهگرهای
qوkروی الگو؛ جدول هر نویسه را باπاش نشان میدهد.