آرایهی پسوندی و LCP
همهی پسوندهای رشته را مرتب میکند و برای هر دو پسوند همسایه طول بلندترین پیشوند مشترک را با روش کاسای در O(n) حساب میکند.
آرایهی پسوندی محل شروع همهی پسوندهای یک رشته است، مرتب بر اساس خود پسوندها. هر زیررشته پیشوندِ یک پسوند است؛ پس با جستوجوی دودویی روی آرایهی پسوندی میشود هر الگو را در O(m log n) پیدا کرد.
- زمان:
O(n² log n) to sort here (O(n log n) with doubling), O(n) for LCP - حافظه:
O(n) - CLRS، بخش ۳۲.۵
banana؛ پسوندهای مرتب: a، ana، anana، banana، na، nana و LCP ها ۰، ۱، ۳، ۰، ۰، ۲.
def suffix_array(S):n = len(S)sa = sorted(range(n), key=lambda i: S[i:]) # the start positions, in the order of their suffixesrows = [[sa[k], S[sa[k]:], "-"] for k in range(n)]rank = [0] * nfor k in range(n):rank[sa[k]] = k# Kasai: going through the suffixes in text order, the common prefix shrinks by at most one each time.h = 0for i in range(n):if rank[i] == 0:h = 0continuej = sa[rank[i] - 1] # the suffix just before S[i:] in sorted orderwhile i + h < n and j + h < n and S[i + h] == S[j + h]:h = h + 1rows[rank[i]][2] = hif h > 0:h = h - 1return sa
شروع اجرا
جدول هنوز خالی است.
متغیرهای محلی
نارنجی = در همین گام عوض شد
Call stack
- suffix_array()خط 1
توضیح
ایده
آرایهی پسوندی محل شروع همهی پسوندهای یک رشته است، مرتب بر اساس خود پسوندها. هر زیررشته پیشوندِ یک پسوند است؛ پس با جستوجوی دودویی روی آرایهی پسوندی میشود هر الگو را در O(m log n) پیدا کرد.
آرایهی LCP
LCP[k] طول بلندترین پیشوند مشترک پسوند k ام و (k−1) ام (در ترتیب مرتب) است. بزرگترین عدد آن، بلندترین زیررشتهی تکرارشونده را میدهد.
روش کاسای
اگر پسوندها را به ترتیب متن (نه ترتیب مرتب) برویم، LCP هر بار حداکثر یکی کم میشود؛ پس h را از مقدار قبلی منهای یک ادامه میدهیم و کل کار O(n) است.
در trace به چه چیزی نگاه کنی
- جدول پسوندهای مرتب است و ستون LCP به ترتیب متن پر میشود؛ اشارهگرهای
iوjدو پسوندیاند که مقایسه میشوند.