妈的,开始sb没用区间操作,找了好久才发现有个地方时间复杂度爆了。。。我一直以为是其他原因导致的超时
发现后线段树搞一搞就ok了,具体的自己yy吧,有益身心健康。。。233
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define N 200010
int Last_n,haha,K;
int Ws[N],Wv[N],sa[N],height[N],Rank[N],f[N][30];
int Use_a[N],Use_b[N],r[N],pos[N],The_len[N];
char S1[N];
int flag[N];
long long Ans[N];
struct Node{
int flag,Max;
}t[N*4];
bool Cmp(int *r,int a,int b,int len)
{
return r[a]==r[b]&&r[a+len]==r[b+len];
}
void Suf_work(int n,int m)
{
int *x=Use_a,*y=Use_b,*t;
for(int i=0;i<m;i++)Ws[i]=0;
for(int i=0;i<n;i++)Ws[x[i]=r[i]]++;
for(int i=1;i<m;i++)Ws[i]+=Ws[i-1];
for(int i=n-1;i>=0;i--)sa[--Ws[x[i]]]=i;
for(int j=1,p=1;p<n;j<<=1,m=p)
{
p=0;
for(int i=n-j;i<n;i++) y[p++]=i;
for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(int i=0;i<n;i++) Wv[i]=x[y[i]];
for(int i=0;i<m;i++) Ws[i]=0;
for(int i=0;i<n;i++) Ws[Wv[i]]++;
for(int i=1;i<m;i++) Ws[i]+=Ws[i-1];
for(int i=n-1;i>=0;i--) sa[--Ws[Wv[i]]]=y[i];
t=x;x=y;y=t;p=1;x[sa[0]]=0;
for(int i=1;i<n;i++)
x[sa[i]]=Cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}
void Calheight(int n)
{
int k=0,j;
for(int i=1;i<=n;i++)Rank[sa[i]]=i;
for(int i=0;i<n;height[Rank[i++]]=k)
for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
}
void RMQ()
{
for(int i=1;i<=Last_n;i++)
f[i][0]=height[i];
for(int j=1;j<=26;j++)
for(int i=1;i<=Last_n;i++)
{
if(i+(1<<j)-1<=Last_n)
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
int Get_min(int a,int b)
{
int x1=Rank[a],x2=Rank[b];
int l=min(x1,x2),r=max(x1,x2);
l++;
if(l>r)
return The_len[a];
int qwer=(int)(log(r-l+1.0)/log(2.0));
return min(f[l][qwer],f[r-(1<<qwer)+1][qwer]);
}
void Pushdown(int i)
{
if(t[i].flag==0)
return;
t[i*2].flag=max(t[i*2].flag,t[i].flag);
t[i*2+1].flag=max(t[i*2+1].flag,t[i].flag);
t[i*2].Max=max(t[i*2].Max,t[i].flag);
t[i*2+1].Max=max(t[i*2+1].Max,t[i].flag);
t[i].flag=0;
}
void Updata(int i,int l,int r,int left,int right,int c)
{
if(l>=left&&r<=right)
{
t[i].flag=max(t[i].flag,c);
t[i].Max=max(t[i].Max,c);
return;
}
Pushdown(i);
int mid=(l+r)/2;
if(right<=mid)
Updata(i*2,l,mid,left,right,c);
else if(left>mid)
Updata(i*2+1,mid+1,r,left,right,c);
else
{
Updata(i*2,l,mid,left,mid,c);
Updata(i*2+1,mid+1,r,mid+1,right,c);
}
t[i].Max=max(t[i*2].Max,t[i*2+1].Max);
}
int Query(int i,int l,int r,int k)
{
if(l==r)
{
return t[i].Max;
}
Pushdown(i);
int mid=(l+r)/2;
if(k<=mid)
return Query(i*2,l,mid,k);
else return Query(i*2+1,mid+1,r,k);
}
int main()
{
int t;cin>>t>>K;
for(int i=1;i<=t;i++)
{
scanf("%s",S1);
int len=(int)strlen(S1);
for(int j=0;j<len;j++)
{
pos[Last_n]=i;
The_len[Last_n]=len-j;
r[Last_n++]=S1[j]-'a'+100000;
}
r[Last_n++]=haha++;
}
Last_n--;
Suf_work(Last_n+1,110000);
Calheight(Last_n);
RMQ();
memset(flag,0,sizeof(flag));
int l1=1,r1=1,l2=0,r2=0,num=0;
for(;l1<=Last_n;l1++)
{
if(r[sa[l1]]<100000)
continue;
if(!l2)
{
flag[pos[sa[l1]]]++;
num=1;
r1=l1;
}
else
{
flag[pos[sa[l2]]]--;
if(!flag[pos[sa[l2]]])
num--;
}
while(num<K&&r1<=Last_n-1)
{
r1++;
if(!flag[pos[sa[r1]]])
{
flag[pos[sa[r1]]]++;
num++;
}
else flag[pos[sa[r1]]]++;
}
if(num<K)
break;
if(l2!=0)
{
for(int i=r2+1;i<r1;i++)
Updata(1,1,200000,i,i,Get_min(sa[l2],sa[i]));
}
Updata(1,1,200000,l1,r1,Get_min(sa[l1],sa[r1]));
l2=l1;r2=r1;
}
if(l2!=0)
{
for(int i=r2+1;i<=Last_n;i++)
Updata(1,1,200000,i,i,Get_min(sa[l2],sa[i]));
}
for(int i=1;i<=Last_n;i++)
{
Ans[pos[sa[i]]]+=Query(1,1,200000,i);
}
for(int i=1;i<=t;i++)
{
printf("%lld ",Ans[i]);
}
cout<<endl;
return 0;
}