HDU 4436 后缀数组
来源:互联网 发布:淘宝估值 编辑:程序博客网 时间:2024/05/17 22:42
点击打开链接
题意:给n个串,求所有的子串去重后相加对2012取余的值
思路:思路借鉴这篇博客,其中有一个求一段串可以形成的和有点类似与字符串hash的想法,用的很巧,要用后缀数组的话不同两个串的连接需要用一个其他的数字,然后正常计算sa和height,然后当遇到的第i个是加的那个数字或者是0都不计算,因为题目说前导不能为0,然后i+height[Rank[i]]要小于i所在的串的结束位置,然后计算的式子就是要加的结果,画一画样例就好理解了
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const ll INF=0x3f3f3f3f3f3f3f3fll;const int MAXN=200010;const int mod=2012;int sa[MAXN];int t1[MAXN],t2[MAXN],c[MAXN];int Rank[MAXN],height[MAXN];void construct_sa(int s[],int n,int m){ int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1){ p=0; for(i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; if(p>=n)break; m=p; }}void construct_lcp(int s[],int n){ int k=0; for(int i=0;i<=n;i++) Rank[sa[i]]=i; for(int i=0;i<n;i++){ if(k)k--; int j=sa[Rank[i]-1]; while(s[i+k]==s[j+k])k++; height[Rank[i]]=k; }}int s[MAXN],id[MAXN],sum[MAXN],T[MAXN],V[MAXN],base[MAXN],arrive[MAXN];char str[MAXN];int calc_sum(int l,int r){ int ans=T[r+1]-T[l]; ans%=mod;ans-=V[l]*base[r-l+1]; ans=(ans+mod)%mod; if(ans<0) ans+=mod; return ans;}int main(){ base[1]=10;for(int i=2;i<MAXN;i++) base[i]=(base[i-1]+1)*10%mod; int n; while(scanf("%d",&n)!=-1){ int k=0,val=0; for(int i=1;i<=n;i++){ scanf("%s",str); int len=strlen(str); for(int j=0;j<len;j++){ s[k]=str[j]-'0'+1; val=(val*10+s[k]-1)%mod; V[k+1]=val; T[k+1]=(T[k]+val)%mod; id[k]=i;k++; } s[k]=11; val=(val*10+10)%mod; V[k+1]=val; T[k+1]=(T[k]+val)%mod; id[k]=i;k++;arrive[i]=k-2; } s[k]=0; construct_sa(s,k+1,128); construct_lcp(s,k); int ans=0; for(int i=0;i<k;i++){ if(s[i]%10!=1){ if(i+height[Rank[i]]<=arrive[id[i]]){//小于这个界限才会有不重复的串 ans+=calc_sum(i,arrive[id[i]])-calc_sum(i,i+height[Rank[i]]-1); ans=(ans+mod)%mod; if(ans<0) ans+=mod; } } } printf("%d\n",ans); } return 0;}
0 0
- hdu 4436 后缀数组
- 后缀数组 HDU 4436
- hdu 4436 后缀数组
- HDU 4436 后缀数组
- hdu 4436 str2int 后缀数组、后缀自动机
- hdu 4436 str2int 后缀数组
- hdu 4436 str2int ( 后缀数组 )
- [后缀数组+思路] hdu 4436 str2int
- hdu 4436 str2int(后缀数组)
- hdu 4416 后缀数组
- hdu 3518后缀数组
- hdu 3518 后缀数组
- HDU 3518 后缀数组
- HDU 4416 后缀数组
- hdu 2492后缀数组
- hdu 4029 后缀数组
- hdu 4416 后缀数组
- hdu 4691 后缀数组
- RS232电平与TTL电平转换
- 图的割点
- UVa 11624 - Fire!(BFS)
- Elasticsearch2.x 全文检索之——查询合并
- handler机制原理源码分析
- HDU 4436 后缀数组
- 框架入门 实战篇 (上)留言板前端整理
- 使用自制的框架完成的留言板完善
- Android、Java验证手机号是否合法
- uva- 156-Ananagrams
- 328. Odd Even Linked List
- 单机安装zookeeper
- Java实现 数据结构之邻接矩阵
- 压缩感知测量矩阵之有限等距性质(Restricted Isometry Property, RIP)