码迷,mamicode.com
首页 > 编程语言 > 详细

UVALive4513 Stammering Aliens(哈希法 | 后缀数组)

时间:2015-12-10 18:56:55      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

 

 

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12580

 

【思路】

       求出现次数不小于k次的最长可重复子串和最后的出现位置。

       法一:

              后缀数组,二分长度,划分height。时间复杂度为O(nlogn)

       法二:

              Hash法。构造字符串的hash函数,二分长度,求出hash(i,L)后排序,判断是否存在超过k个相同hash 值得块即可。时间为O(nlog2n).

       注意划分height一定要精确且如果m=1需要特判(对于该模板来说)。

 

【代码1】

 

技术分享
 1 //193ms 
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 
 7 const int maxn = 80000+10; 
 8 
 9 int s[maxn];
10 int sa[maxn],c[maxn],t[maxn],t2[maxn];
11 void build_sa(int m,int n) {
12     int i,*x=t,*y=t2;
13     for(i=0;i<m;i++) c[i]=0;
14     for(i=0;i<n;i++) c[x[i]=s[i]]++;
15     for(i=1;i<m;i++) c[i]+=c[i-1];
16     for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
17     for(int k=1;k<=n;k<<=1) {
18         int p=0;
19         for(i=n-k;i<n;i++) y[p++]=i;
20         for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
21         for(i=0;i<m;i++) c[i]=0;
22         for(i=0;i<n;i++) c[x[y[i]]]++;
23         for(i=0;i<m;i++) c[i]+=c[i-1];
24         for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
25         swap(x,y);
26         p=1; x[sa[0]]=0;
27         for(i=1;i<n;i++) 
28             x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
29         if(p>=n) break;
30         m=p;
31     }
32 }
33 int rank[maxn],height[maxn];
34 void getHeight(int n) {
35     int i,j,k=0;
36     for(i=0;i<=n;i++) rank[sa[i]]=i;
37     for(i=0;i<n;i++) {
38         if(k) k--;
39         j=sa[rank[i]-1];
40         while(s[j+k]==s[i+k]) k++;
41         height[rank[i]]=k;
42     }
43 }
44 int limit,n,pos;
45 bool can(int L) {    //一定要注意划分height数组的准确性 
46     pos=-1;
47     int cnt=1,mx=sa[1];
48     for(int i=2;i<=n;i++) {
49         mx=max(mx,sa[i]);
50         if(height[i]<L) cnt=1,mx=sa[i];
51         else {
52             if(++cnt>=limit) pos=max(pos,mx);
53         }
54     }
55     return pos>=0;
56 }
57 
58 char expr[maxn];
59 int main() {
60     //freopen("in.in","r",stdin);
61     //freopen("out.out","w",stdout);
62     while(scanf("%d",&limit)==1 && limit) {
63         scanf("%s",expr);
64         n=strlen(expr);
65         for(int i=0;i<n;i++) s[i]=expr[i]; s[n]=0;
66         
67         build_sa(z+1,n+1);
68         getHeight(n);
69         
70         if(limit==1) { printf("%d 0\n",n); continue; }
71         int L=1,R=n+1;
72         while(L<R) {
73             int M=L+(R-L+1)/2;
74             if(can(M)) L=M; else R=M-1;
75         }
76         if(!can(L)) printf("none\n");
77         else printf("%d %d\n",L,pos);
78     }
79     return 0;
80 }
da

 

【代码2】

 

技术分享
 1 //1628ms
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 typedef unsigned long long ULL;
 9 const int maxn = 80000+10;
10 const int x = 233;
11 
12 ULL hash[maxn],xp[maxn],H[maxn];
13 int m,n;
14 char s[maxn];
15 
16 int cmp(const int& a,const int& b) {
17     return hash[a]<hash[b] || (hash[a]==hash[b] && a<b);
18 }
19 int pos,rank[maxn];
20 bool can(int L) {
21     pos=-1;
22     for(int i=0;i<n-L+1;i++) hash[i]=H[i]-H[i+L]*xp[L],rank[i]=i;
23     sort(rank,rank+n-L+1,cmp);
24     int cnt=0;
25     for(int i=0;i<n-L+1;i++) {
26         if(!i || hash[rank[i]]!=hash[rank[i-1]]) cnt=0;
27         if(++cnt>=m) pos=max(pos,rank[i]);
28     }
29     return pos>=0;
30 }
31 
32 int main() {
33     //freopen("in.in","r",stdin);
34     //freopen("outr.out","w",stdout);
35     while(scanf("%d",&m)==1 && m) {
36         scanf("%s",s);
37         n=strlen(s);
38         
39         H[n]=0,xp[0]=1;
40         for(int i=n-1;i>=0;i--) H[i]=H[i+1]*x+s[i]-a;
41         for(int i=1;i<=n;i++) xp[i]=xp[i-1]*x;
42         
43         if(!can(1)) printf("none\n");
44         else {
45             int L=1,R=n+1;
46             while(L<R) {
47                 int M=L+(R-L+1)/2;
48                 if(can(M)) L=M;  else R=M-1;
49             }
50             can(L);
51             printf("%d %d\n",L,pos);
52         }
53     }
54     return 0;
55 }
hash

 

UVALive4513 Stammering Aliens(哈希法 | 后缀数组)

标签:

原文地址:http://www.cnblogs.com/lidaxin/p/5036751.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!