比赛 |
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;
}