比赛 20160415 评测结果 AAAAAAAAAA
题目名称 字符串 最终得分 100
用户昵称 前鬼后鬼的守护 运行时间 0.427 s
代码语言 C++ 内存使用 26.38 MiB
提交时间 2016-04-15 11:50:55
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<algorithm>
#define FILE "stringa"
typedef long long ll;
typedef double lf;
using std::max;
using std::min;
namespace IO{
	char buf[1<<15],*fs,*ft;
	inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline int read(){
		int x=0,rev=0,ch=getc();
		while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getc();}
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getc();}
		return rev?-x:x;
	}
}using namespace IO;
const int MAXN(100000*2),MAXL(MAXN*2),D(50),INF(1<<30);
int n,len,K,belong[MAXN+D];
int right[MAXL+D];
namespace SuffixArrary{
	int str[MAXL+D],sa[MAXL+D],rank[MAXL*2+D],height[MAXL+D];
	inline bool equ(int x,int y,int l){return rank[x]==rank[y]&&rank[x+l]==rank[y+l];}
	void doubling(){
		static int p[MAXL+D],temp[MAXL+D],cnt[MAXL+D];
		for(int i=1;i<=len;i++)rank[i]=str[i],sa[i]=i;
		for(int i,l=0,pos=0,sig=26+n;pos<len;sig=pos){
			for(pos=0,i=len-l+1;i<=len;i++)p[++pos]=i;
			for(i=1;i<=len;i++)if(sa[i]>l)p[++pos]=sa[i]-l;
			memset(cnt+1,0,sizeof(int)*(sig));
			for(i=1;i<=len;i++)cnt[rank[i]]++;
			for(i=1;i<=sig;i++)cnt[i]+=cnt[i-1];
			for(i=len;i;i--)sa[cnt[rank[p[i]]]--]=p[i];
			for(i=1,pos=0;i<=len;i++)
				temp[sa[i]]=(equ(sa[i],sa[i-1],l)?pos:++pos);
			memcpy(rank+1,temp+1,sizeof(int)*len);
			l=!l?1:l<<1;
		}
		for(int i=1,j,k=0;i<=len;i++){
			if(k)k--;
			if(rank[i]==1){height[rank[i]]=k=0;continue;}
			for(j=sa[rank[i]-1];str[i+k]==str[j+k];k++);
			height[rank[i]]=k;
		}
	}
}using namespace SuffixArrary;
void init(){
	static int cnt[MAXN+D];
	n=read(),K=read();
	if(K==1){
		for(int i=1;i<=n;i++){
			int len=0;
			char ch=getc();
			while(ch<'a'||ch>'z')ch=getc();
			while(ch>='a'&&ch<='z')
				len++,ch=getc();
			printf("%I64d ",1LL*(len+1)*len>>1);
		}
		exit(0);
	}
	for(int i=1;i<=n;i++){
		char ch=getc();
		while(ch<'a'||ch>'z')ch=getc();
		while(ch>='a'&&ch<='z')
			str[++len]=ch-'a'+1,belong[len]=i,ch=getc();
		str[++len]=26+i;
	}
	doubling();
	n=len-n;
	/*for(int i=1;i<=n;i++)
		printf("%d ",sa[i]);
	printf("\n");
	for(int i=1;i<=n;i++)
		printf("%d ",height[i]);
	printf("\n");*/
	for(int l=1,r=1,num=0;l<=n;l++){
		while(r<=n&&num<K){
			if(!(cnt[belong[sa[r]]]++)&&(++num)==K)
				break;
			r++;
		}
		right[l]=r;
		if(!(--cnt[belong[sa[l]]]))
			num--,r++;
	}
	/*for(int i=1;i<=n;i++)
		printf("%d ",right[i]);
	printf("\n");*/
}
namespace Segment_Tree{
	int L,t[MAXL*4+D];
	inline void update(int n){for(L=1;L-2<n;L<<=1);}
	inline void change(int x,int y,int k){
		for(int left=L+x-1,right=L+y+1;left^right^1;left>>=1,right>>=1){
			if(!(left&1))t[left^1]=max(t[left^1],k);
			if(right&1)t[right^1]=max(t[right^1],k);
		}
	}
	inline int req(int x){
		int ans=0;
		for(int p=L+x;p;p>>=1)
			ans=max(ans,t[p]);
		return ans;
	}
}
struct Data{
	int pos,h;
}d[MAXL+D];
inline bool operator<(const Data& a,const Data& b){return a.h>b.h;}
struct Seg{
	int l,r,par;
}s[MAXL+D];
inline int find(int x){
	int f=x;while(f!=s[f].par)f=s[f].par;
	while(x!=f){int t=s[x].par;s[x].par=f;x=t;}
	return f;
}
inline Seg& merge(int x,int y){
	x=find(x),y=find(y);
	s[x].l=min(s[x].l,s[y].l);
	s[x].r=max(s[x].r,s[y].r);
	s[y].par=x;
	return s[x];
}
void work(){
	for(int i=1;i<=n;i++)d[i].pos=i,d[i].h=height[i];
	std::sort(d+1,d+n+1);
	for(int i=1;i<=n;i++)s[i].l=s[i].r=s[i].par=i;
	Segment_Tree::update(n);
	for(int l=1,r=1;l<=n;l=++r){
		while(r<n&&d[r+1].h==d[r].h)
			r++;
		for(int i=l;i<=r;i++){
			Seg temp=merge(d[i].pos-1,d[i].pos);
			if(temp.r>=right[temp.l])
				Segment_Tree::change(temp.l,temp.r,d[r].h);
		}
	}
	ll cnt=0;
	for(int i=1;i<=len;i++){
		if(!belong[i])printf("%I64d ",cnt),cnt=0;
		else cnt+=Segment_Tree::req(rank[i]);
	}
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	init();
	work();
	return 0;
}