1. 程式人生 > >bzoj2882工藝(最小表示法)

bzoj2882工藝(最小表示法)

const display 後綴 main while 發現 sam can pen

O(nlogn)的做法十分顯然,有三種可以做到O(nlogn)的:1、最容易的想法:把串擴展成兩倍,然後跑一遍SA求後綴數組。2、求後綴同樣也可以用SAM去求解,用map存一下。3、最暴力的方法:直接二分+hash比較第一位不同的。

其實這題想要讓我們用最小表示法求解,然而我不會就來學一下。很容易發現這樣一個規律,如果存在s[i+k]>s[j+k],那麽s[i...i+k]開頭的都不會是最小表示法開頭,因為s[i...i+k]=s[j...j+k],所以從s[i...i+k]開頭的串都會經過這裏。出現這種情況,直接i+=k即可。又簡便又好寫,不過這種方法很容易忘。

技術分享圖片
#include<bits/stdc++.h>
using
namespace std; const int N=6e5+7; int n,a[N]; int solve() { int i=1,j=2; while(i<=n&&j<=n) { int k=0; while(j+k<=2*n&&a[i+k]==a[j+k])k++; if(j+k>2*n)break; if(a[i+k]>a[j+k])i=max(j,i+k+1),j=i+1; else j+=k+1
; } return min(i,j); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i+n]=a[i]; int pos=solve(); for(int i=pos;i<pos+n;i++)printf("%d ",a[i]); }
View Code

bzoj2882工藝(最小表示法)