UVALive - 4513 Stammering Aliens

Face questions

 

Today brushed up suffix array. . . Feel forgotten hhhhh

As for what suffix array is how to write like not presented here, talk about how to do with it this problem.

We done it again suffix array, you can get rank [i] (represents the lexicographical rank subscript i started suffix), sa [i] (can be understood as rank [i] of the inverse function? Lexicographical ranked as i suffix subscript), H [i] (lexicographic lexicographically ranked ranked suffix i is the suffix i-1 LCP) three arrays, then we need only O (N) swept again, for each i> = m click request min ([i] h, h [i-1], ....., h [i-m + 2]) and used to update answers. Of course, the location updating is max (sa [i], sa [i-1], ....., sa [i-m + 1]).

 

I will not speak how O (N) to achieve this, and why row directly with a continuous period of updating will be able to answer after a good sequence? This is because if we choose not continuous period, then did not choose between the extreme left and the extreme right elements fill, lcp and will not change, and it will increase the number of occurrences, it can prove continuous period will be able to find answer.

 

Then we found that, min required (h [i], h [i-1], ....., h [i-m + 2]) and max (sa [i], sa [i-1], ....., sa [i-m + 1]), the interval length is fixed, each right end of the right one, it is naturally conceivable monotonous queue optimization.

 

(Incidentally, leave the board, after too lazy to hand fighting evil suffix array tired and I)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=40005;

int r[N*2],rx[N],sa[N],sax[N],M,P,cc[N];
int h[N],sec[N],n,m,q[N],L,R,Q[N],l,rr;
char s[N];

inline void init(){
	memset(s,0,sizeof(s));
	memset(cc,0,sizeof(cc));
	memset(sa,0,sizeof(sa));
	memset(r,0,sizeof(r));	
}

inline void build(){
	for(int i=0;i<n;i++) cc[s[i]]++;
	for(int i=1;i<=500;i++) cc[i]+=cc[i-1];
	for(int i=0;i<n;i++) sa[cc[s[i]]--]=i;
	for(int i=1;i<=n;i++){
		r[sa[i]]=i;
		if(i>1&&s[sa[i]]==s[sa[i-1]]) r[sa[i]]=r[sa[i-1]];
	}
	
	for(int k=1;k<n;k<<=1){
		fill(cc,cc+n+1,0);
		
		for(int i=0;i<n;i++) cc[sec[i]=r[i+k]]++;
		for(int i=n-1;i>=0;i--) cc[i]+=cc[i+1];
		for(int i=0;i<n;i++) sax[cc[sec[i]]--]=i;
		
		fill(cc,cc+n+1,0);
		
		for(int i=0;i<n;i++) cc[r[i]]++;
		for(int i=1;i<=n;i++) cc[i]+=cc[i-1];
		for(int i=1;i<=n;i++) sa[cc[r[sax[i]]]--]=sax[i];
		for(int i=1;i<=n;i++){
            rx[sa[i]]=i;
            if(i>1&&r[sa[i]]==r[sa[i-1]]&&sec[sa[i]]==sec[sa[i-1]]) rx[sa[i]]=rx[sa[i-1]];
		}
		
		for(int i=0;i<n;i++) r[i]=rx[i];
	}
	
	int now=0,j,mx;
	for(int i=0;i<n;i++){
		if(r[i]==1){
			h[r[i]]=now=0;
			continue;
		}
		
		if(now) now--;
		j=sa[r[i]-1],mx=max(i,j);
		while(mx+now<n&&s[i+now]==s[j+now]) now++;
		
		h[r[i]]=now;
	}
}

inline void solve(){
	m--,L=1,R=0,Q[l=rr=1]=1,M=P=0;
	
//	for(int i=1;i<=n;i++) printf("%d %d\n",sa[i],h[i]);
	
	for(int i=2;i<=n;i++){
		while(L<=R&&h[i]<=h[q[R]]) R--;
		q[++R]=i;
		while(L<=R&&i-q[L]>=m) L++;
		
		while(l<=rr&&sa[i]>=sa[Q[rr]]) rr--;
		Q[++rr]=i;
		while(l<=rr&&i-Q[l]>m) l++;		
		
		if(i<=m) continue;
		
		if(h[q[L]]>M) M=h[q[L]],P=sa[Q[l]];
		else if(h[q[L]]==M) P=max(P,sa[Q[l]]);
	}
	
	if(!M) puts("none");
	else printf("%d %d\n",M,P);
}

int main(){
	while(scanf("%d",&m)==1&&m){
		init(),scanf("%s",s),n=strlen(s);
		if(m==1){ printf("%d %d\n",n,0); continue;}
		
		build();
		
		solve();
	}
	
	return 0;
}

  

Guess you like

Origin www.cnblogs.com/JYYHH/p/11279215.html