做完这道题终于知道了什么叫做绝望。。
首先,这道题的读入坑到我wa了一页,然后这道题的读入坑了我一晚上,最后这道题的读入吧我玩废了。。
用血写出来的经验最后一个字符要赋'\0'。。
好了说说这道题后缀数组的做法:
把每个单词拼在一起中间由分隔符分开然后做一遍后缀数组,观察sa数组,容易发现如果一个单词包括另一个单词显然要有height[i]大于等于这个单词,如果height[i]小于这单词显然之前或之后的都不包括这个单词,所以二分左右端点+rmq最小,如果区间rmq的height小于这个单词的height就继续二分,但是这道题的n比较小所以rmq卡的跟暴力一样。。
UPDATE(7.19):我们可以理解一下这个RMQ,其实是类似单调栈的思想。
一个小姿势:rmg的手写log2比较快
就是这一段:
log2[0]=-1;
for(int i=1;i<=x;i++)
log2[i]=log2[i>>1]+1;
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int Maxn=1100000;
char s[Maxn];
int tax[Maxn],tp[Maxn],sa[Maxn],rank[Maxn],height[Maxn],ks[Maxn],length[Maxn],Min[Maxn][25],log2[Maxn];
int n,x=0,m=256;
inline void Rsort()
{
for(int i=1;i<=m;i++)
tax[i]=0;
for(int i=1;i<=x;i++)
tax[rank[tp[i]]]++;
for(int i=1;i<=m;i++)
tax[i]+=tax[i-1];
for(int i=x;i>=1;i--)
sa[tax[rank[tp[i]]]--]=tp[i];
}
inline int cmp(int *f,int x,int y,int w)
{
return (f[x]==f[y])&&(f[x+w]==f[y+w]);
}
inline void suffix()
{
for(int i=1;i<=x;i++)
tp[i]=i,rank[i]=s[i];
Rsort();
for(int p=1,w=1,i;p<x;w+=w,m=p)
{
for(p=0,i=x-w+1;i<=x;i++)
tp[++p]=i;
for(i=1;i<=x;i++)
if(sa[i]>w)
tp[++p]=sa[i]-w;
Rsort();
swap(rank,tp);
rank[sa[1]]=p=1;
for(i=2;i<=x;i++)
rank[sa[i]]=cmp(tp,sa[i],sa[i-1],w)?p:++p;
}
for(int i=1,j,p;i<=x;height[rank[i]]=j,i++)
for(j=max(height[rank[i-1]]-1,0),p=sa[rank[i]-1];s[p+j]==s[i+j];j++);
}
inline int rmq(int q1,int q2)
{
if(q1>q2)
return 0x3f3f3f3f;
return min(Min[q1][log2[q2-q1+1]],Min[q2-(1<<log2[q2-q1+1])+1][log2[q2-q1+1]]);
}
inline int L_binary(int rt)
{
int l=1,r=rank[ks[rt]];
while(r-l>1)
{
int mid=(l+r)>>1;
if(rmq(mid+1,rank[ks[rt]])>=length[rt])
r=mid;
else
l=mid;
}
if(rmq(l+1,rank[ks[rt]])>=length[rt])
return l;
else
return r;
}
inline int R_binary(int rt)
{
int l=rank[ks[rt]],r=x;
while(r-l>1)
{
int mid=(l+r)>>1;
if(rmq(rank[ks[rt]]+1,mid)>=length[rt])
l=mid;
else
r=mid;
}
if(rmq(rank[ks[rt]]+1,r)>=length[rt])
return r;
else
return l;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1+ks[i-1]+length[i-1]);
length[i]=strlen(s+1+ks[i-1]+length[i-1]);
ks[i]=++x;
x=x+length[i];
s[x]='@';
}
s[x]=0;
x--;
suffix();
height[1]=0;
log2[0]=-1;
for(int i=1;i<=x;i++)
log2[i]=log2[i>>1]+1;
for(int i=1;i<=x;i++)
Min[i][0]=height[i];
for(int j=1;j<=log2[x];j++)
for(int i=1;i+(1<<j)-1<=x;i++)
Min[i][j]=min(Min[i][j-1],Min[i+(1<<j-1)][j-1]);
for(int i=1;i<=n;i++)
{
int l=L_binary(i);
int r=R_binary(i);
printf("%d\n",r-l+1);
}
return 0;
}