1. 程式人生 > >Uva 12206 Stammering Aliens

Uva 12206 Stammering Aliens

region load png highlight return string mat reg tdi

題目描述

技術分享圖片

輸入輸出格式

輸入格式:

技術分享圖片

輸出格式:

技術分享圖片

輸入輸出樣例

輸入樣例#1:
3
baaaababababbababbab
11
baaaababababbababbab
3
cccccc
0
輸出樣例#1:
5 12
none
4 2


這個題後綴數組或者二分+hash好像都能做,,,但是我只是練一下後綴自動機而已hhhhh
這個題我們求的顯然就是right集合大小>=m的max{}的最大值,至於求最右開端的話,我們只需要記錄一下
right集合的最右點是哪個就行了,然後用這個減去答案長度就是最右開端。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define maxn 170005
using namespace std;
int l[maxn],siz[maxn],n,r[maxn];
int cnt=1,pre=1,m,ans,pos;
int ch[maxn][26],f[maxn];
int a[maxn],c[maxn];
char s[maxn];

inline void init(){
	memset(ch,0,sizeof(ch));
	memset(f,0,sizeof(f));
	memset(c,0,sizeof(c));
	memset(siz,0,sizeof(siz));
	memset(r,0,sizeof(r));
	cnt=pre=1,l[1]=siz[1]=0;
	ans=pos=0;
}

inline void ins(int x){
	int p=pre,np=++cnt;
	pre=np,l[np]=l[p]+1;
	siz[np]=1,r[np]=l[np];
	
	for(;p&&!ch[p][x];p=f[p]) ch[p][x]=np;
	if(!p) f[np]=1;
	else{
		int q=ch[p][x];
		if(l[q]==l[p]+1) f[np]=q;
		else{
			int nq=++cnt;
			l[nq]=l[p]+1;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			f[nq]=f[q];
			f[q]=f[np]=nq;
			for(;ch[p][x]==q;p=f[p]) ch[p][x]=nq;
		}
	}
}

inline void build(){
	for(int i=0;i<n;i++) ins(s[i]-‘a‘);
	for(int i=1;i<=cnt;i++) c[l[i]]++;
	for(int i=n;i>=0;i--) c[i]+=c[i+1];
	for(int i=1;i<=cnt;i++) a[c[l[i]]--]=i;
}

inline void solve(){
	for(int i=1;i<=cnt;i++){
		int now=a[i];
		siz[f[now]]+=siz[now];
		r[f[now]]=max(r[f[now]],r[now]);
		if(l[now]&&siz[now]>=m){
			if(l[now]>ans) ans=l[now],pos=r[now];
			else if(ans==l[now]&&r[now]>pos) pos=r[now];
		}
	}
}

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

  



Uva 12206 Stammering Aliens