某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
标签:iostream stream 接下来 中间 print can == struct n+1
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
思维越来越僵化。。。又是一道后缀数组傻逼题。。。
把所有的串拼在一起,中间用"#"隔开,然后记录每个串开始的位置st[i]和长度le[i]。
因为n很小可以每个串暴力;如果该串在别的串出现,那么以st[i]开头的后缀与别的后缀的lcp长度为le[i];
因为排名越靠近height越大,所以从rnk[st[i]]往左右两边扫,直到height小于le[i],则分组中的lcp长度为le[i],是所有的出现情况。
// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=3000050;
int gi(){
int x=0,flag=1;
char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) flag=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
return x*flag;
}
int sa[N],y[N],rnk[N],height[N],len,rk,le[N],st[N],n;
char ch[N],a[N];
struct data{
int x1,x2,id;
}x[N];
bool cmp(const data &a,const data &b){
if(a.x1==b.x1) return a.x2<b.x2;
else return a.x1<b.x1;
}
void work2(){
int rk=1;y[x[1].id]=1;
for(int i=2;i<=len;i++){
if(x[i].x1!=x[i-1].x1||x[i].x2!=x[i-1].x2) rk++;
y[x[i].id]=rk;
}
}
void work(){
sort(x+1,x+1+len,cmp);work2();
for(int i=1;i<=len;i<<=1){
for(int j=1;j+i<=len;j++) x[j].id=j,x[j].x1=y[j],x[j].x2=y[j+i];
for(int j=len-i+1;j<=len;j++) x[j].id=j,x[j].x1=y[j],x[j].x2=0;
sort(x+1,x+1+len,cmp);work2();
if(rk==len) break;
}
}
void get_height(){
int kk=0;for(int i=1;i<=len;i++) rnk[sa[i]]=i;
for(int i=1;i<=len;i++){
if(kk) kk--;
int j=sa[rnk[i]-1];
while(a[i+kk]==a[j+kk]) kk++;
height[rnk[i]]=kk;
}
}
void work3(int i){
ll ret=1;int l=rnk[st[i]],r=rnk[st[i]]+1;
while(height[l]>=le[i]) ret++,l--;
while(height[r]>=le[i]) ret++,r++;
printf("%lld\n",ret);
}
int main(){
n=gi();
for(int i=1;i<=n;i++){
scanf("%s",ch+1);le[i]=strlen(ch+1);st[i]=len+1;
for(int j=1;j<=le[i];j++) a[len+j]=ch[j];
len+=le[i]+1;a[len]=‘#‘;
}
for(int i=1;i<=len;i++) x[i].id=i,x[i].x1=x[i].x2=a[i]-‘a‘+1;
work();for(int i=1;i<=len;i++) sa[y[i]]=i;
get_height();
for(int i=1;i<=n;i++) work3(i);
return 0;
}
标签:iostream stream 接下来 中间 print can == struct n+1
原文地址:http://www.cnblogs.com/qt666/p/7106994.html