【jzoj3870】【单词检索】【后缀数组】
2017-01-16 11:42
351 查看
题目大意
由于学校需要一些材料,校长需要在文章中检索一些信息。校长一共给了小可可N篇文章,每篇文章为一个字符串。现在,校长需要他找到这样的单词,它至少在这N篇文章中的M篇文章里出现过,且单词长度为L。可是,工作量十分庞大,但校长又急需小可可完成这项任务。现在他向你求助,需要你编写程序完成这项艰巨的任务。
解题思路
题解是hash。我使用的是sa。考虑把所有的串并在一起,中间用没出现过的符号分隔。按height>=l分组,看每组的串是否来自>=m个串,统计答案即可。
code
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define LF double #define LL long long #define min(a,b) ((a<b)?a:b) #define max(a,b) ((a>b)?a:b) #define fo(i,j,k) for(int i=j;i<=k;i++) #define fd(i,j,k) for(int i=j;i>=k;i--) using namespace std; int const maxn=2000,maxl=1000,inf=1e9; int n,m,l,N,M,cnt[maxn*maxl+10],A[2][maxn*maxl+10],sa[maxn*maxl+10], h[maxn*maxl+10],num[maxn*maxl+10],s[maxn*maxl+10]; int *rank=A[0],*ord=A[1]; char S[maxl+10]; void sort(){ fo(i,0,M)cnt[i]=0; fo(i,1,N)cnt[rank[i]]++; fo(i,1,M)cnt[i]+=cnt[i-1]; fd(i,N,1)sa[cnt[rank[ord[i]]]--]=ord[i]; } bool diff(int x,int y,int w){ return (ord[x]!=ord[y])||(ord[x+w]!=ord[y+w]); } int main(){ freopen("d.in","r",stdin); freopen("d.out","w",stdout); scanf("%d%d%d",&n,&m,&l);N=1;int len; fo(cas,1,n){ scanf("%s",S);len=strlen(S); fo(i,N,N+len-1)num[i]=cas,s[i]=S[i-N]; s[N+len]=256+cas;N+=len+1; }N--;M=256+n; fo(i,1,N)rank[i]=s[i],ord[i]=i; sort(); for(int w=1,p=0;p<N;w=w<<1){ M=p,p=0;fo(i,N-w+1,N)ord[++p]=i; fo(i,1,N)if(sa[i]>w)ord[++p]=sa[i]-w; sort();swap(rank,ord);rank[sa[1]]=p=1; fo(i,2,N)rank[sa[i]]=(p+=diff(sa[i-1],sa[i],w)); } for(int i=1,p=0;i<=N;h[rank[i]]=p,i++) for(p-=(p!=0);s[i+p]==s[sa[rank[i]-1]+p];p++); int ans=0;fo(i,1,n)cnt[i]=0; for(int i=1,j,tmp;i<=N;){ j=i;tmp=0;while((j<N)&&(h[j+1]>=l))j++; fo(k,i,j){ if(!cnt[num[sa[k]]])tmp++; cnt[num[sa[k]]]=1; } if(tmp>=m) ans++; fo(k,i,j)cnt[num[sa[k]]]=0; i=j+1; } printf("%d",ans); return 0; }
相关文章推荐
- JZOJ 3870. 【NOIP2014八校联考第4场第1试10.19】单词检索(search)
- 【JZOJ3870】【NOIP2014八校联考第4场第1试10.19】单词检索(search)
- 【JZOJ 3870】 单词检索
- 【JZOJ 3870】单词检索
- 后缀数组基数排序——bzoj3172: [Tjoi2013]单词
- 【后缀数组】JZOJ1598
- 【jzoj5084】【GDOI2017第四轮模拟day1】【子串】【后缀数组】
- bzoj 3172 单词 ac自动机|后缀数组
- 【jzoj3277】【GDOI2013】【哈希和】【后缀数组】
- 后缀数组 查找单词
- JZOJ3870. 【NOIP2014八校联考第4场第1试10.19】单词检索(search)
- [AC自动机 fail树 || 后缀数组] BZOJ 3172 [Tjoi2013]单词
- POJ1743 Musical Theme,后缀数组,最长重复不重叠子串,二分检索答案
- 后缀数组 【TJOI2013】 bzoj3172 单词
- BZOJ 题目3172: [Tjoi2013]单词(AC自动机||AC自动机+fail树||后缀数组暴力||后缀数组+RMQ+二分等五种姿势水过)
- poj3261(后缀数组求至少出现k次的最长子串可重叠)
- poj 2774 Long Long Message 后缀数组基础题
- 后缀数组--倍增法实现
- 利用后缀数组求最长的重复子串
- URAL 1297. Palindrome(后缀数组 求最长回文子串)