[bzoj3172] [Tjoi2013]單詞
阿新 • • 發佈:2019-01-12
Description
某人讀論文,一篇論文是由許多單片語成。但他發現一個單詞會在論文中出現很多次,現在想知道每個單詞分別在論文中出現多少次。
Input
第一個一個整數N,表示有多少個單詞,接下來N行每行一個單詞。每個單詞由小寫字母組成,N<=200,單詞長度不超過10^6
Output
輸出N個整數,第i行的數字表示第i個單詞在文章中出現了多少次。
Sample Input
3
a
aa
aaa
Sample Output
6
3
1
Solution
字尾陣列,求出\(height\)之後怎麼暴力怎麼寫。
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } void print(int x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} const int maxn = 1.1e6+10; int st[maxn],len[maxn]; char tmp[maxn]; int N,cnt; struct Suffix_Array { char s[maxn]; int sa[maxn],Sp1[maxn],Sp2[maxn],sum[maxn],height[maxn],rk[maxn],m,n; void build() { int *x=Sp1,*y=Sp2; n=strlen(s+1),m=130; for(int i=1;i<=m;i++) sum[i]=0; for(int i=1;i<=n;i++) sum[x[i]=s[i]]++; for(int i=1;i<=m;i++) sum[i]+=sum[i-1]; for(int i=n;i;i--) sa[sum[x[i]]--]=i; for(int k=1,p=0,tot=0;p<n;k<<=1,tot=0) { for(int i=n-k+1;i<=n;i++) y[++tot]=i; for(int i=1;i<=n;i++) if(sa[i]>k) y[++tot]=sa[i]-k; for(int i=1;i<=m;i++) sum[i]=0; for(int i=1;i<=n;i++) sum[x[y[i]]]++; for(int i=1;i<=m;i++) sum[i]+=sum[i-1]; for(int i=n;i;i--) sa[sum[x[y[i]]]--]=y[i]; swap(x,y);x[sa[1]]=p=1; for(int i=2;i<=n;i++) if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) x[sa[i]]=++p; else x[sa[i]]=p; m=p; } } void get_height() { for(int i=1;i<=n;i++) rk[sa[i]]=i; for(int i=1,p=1;i<=n;i++) { if(p) p--; while(s[i+p]==s[sa[rk[i]-1]+p]) p++; height[rk[i]]=p; } } void solve() { for(int i=1;i<=N;i++) { int ans=0; for(int j=rk[st[i]];j;j--) if(height[j]>=len[i]) ans++; else break; for(int j=rk[st[i]]+1;j<=n;j++) if(height[j]>=len[i]) ans++; else break; write(ans+1); } } }SA; int main() { read(N); for(int i=1;i<=N;i++) { scanf("%s",tmp+1); len[i]=strlen(tmp+1);st[i]=cnt+1; for(int j=1;j<=len[i];j++) SA.s[++cnt]=tmp[j]; SA.s[++cnt]='$'; } //cout << SA.s+1 << endl; SA.build();SA.get_height(); SA.solve(); return 0; }