【字尾陣列】[POJ 1743]Musical Theme
阿新 • • 發佈:2018-12-24
題目分析
字尾陣列模板題目,我們可以二分一下答案然後我們在構建的每兩個數的差所求得的height陣列中查詢當前連續大於mid的一個區間的pos最小和pos最大值得差值,然後如果這個差值大於了mid我們才認為可以使用,否則會因為有一個節點重疊(相當於每一個差值表示的是一條邊,如果剛好相等,那麼這兩個邊的一對端點是重合的)
這裡有幾點要注意
- 字尾陣列時最後一個迴圈要反著
- 字尾陣列在判斷rank的種類是否大於等於n時要在迴圈底部,不應在條件中否則有可能無法進入迴圈
- 注意統計數量的陣列一定要和存放n的陣列大小相同
程式碼
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 500000;
int sa[MAXN+10], r1[MAXN+10], r2[MAXN+10], counter[MAXN+10], height[MAXN+10];
void buildsa(int *s, int len, int kind){
for(int i=0;i<=kind;i++) counter[i] = 0;
for(int i=1;i<=len;i++) counter[r1[i]=s[i]]++;
for(int i=0;i<=kind;i++) counter[i] += counter[i-1];
for(int i=len ;i>=1;i--) sa[counter[r1[i]]--] = i;
for(int i=1;i<len;i<<=1){
int p = 0;
for(int j=len-i+1; j<=len; j++) r2[++p] = j;
for(int j=1;j<=len;j++)
if(sa[j] > i)
r2[++p] = sa[j] - i;
for(int j=0;j<=kind;j++) counter[j] = 0 ;
for(int j=1;j<=len;j++) counter[r1[r2[j]]]++;
for(int j=0;j<=kind;j++) counter[j] += counter[j-1];
for(int j=len;j>=1;j--) sa[counter[r1[r2[j]]] --] = r2[j];
swap(r1, r2);
r1[sa[1]] = kind = 1;
for(int j=2;j<=len;j++)
r1[sa[j]] = (r2[sa[j]] == r2[sa[j-1]] && r2[sa[j]+i] == r2[sa[j-1]+i]) ? kind : ++kind;
if(kind >= len) break;
}
int now = 0;
for(int i=1;i<=len;i++){
if(r1[i] == 1){
height[r1[i]] = now = 0;
}else{
now = max(now-1, 0);
int j = sa[r1[i]-1];
while(s[i+now] == s[j+now]) now++;
height[r1[i]] = now;
}
}
}
bool check(int L, int n){
int Minpos = sa[1], Maxpos = sa[1];
for(int i=2;i<n;i++){
if(height[i] >= L){
Minpos = min(Minpos, sa[i]);
Maxpos = max(Maxpos, sa[i]);
}else{
if(Maxpos - Minpos > L) return true;
Minpos = Maxpos = sa[i];
}
}
return Maxpos - Minpos > L;
}
int s[MAXN+10];
int main(){
int n;
while(scanf("%d", &n), n){
for(int i=1;i<=n;i++)
scanf("%d", &s[i]);
for(int i=2;i<=n;i++)
s[i-1] = s[i] - s[i-1] + 100;
s[n] = 0;
buildsa(s, n-1, 300);
int l = 0, r = n-1, ans=0;
while(l <= r){
int mid = (l + r) >> 1;
if(check(mid, n-1)){
ans = mid;
l = mid+1;
}else r = mid-1;
}
if(ans < 4) printf("%d\n", 0);
else printf("%d\n", ans+1);
}
return 0;
}