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

题目链接: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

时间: 2024-11-05 09:46:06

UVALive4513 Stammering Aliens(哈希法 | 后缀数组)的相关文章

POJ 3882/LA4513/HDU4080/ZOJ3395 Stammering Aliens 题解【后缀自动机】

题意:求一个串中可重叠至少出现m次的最长子串,并且求出该串最后一次出现的起始位置. 找了一下网上并没有SAM做法的题解..我来说一下好了 首先每个SAM上的结点需要多保存两个值:cnt和right.cnt代表该状态right集合大小,right值是right集合中最大的那个值(right集合定义见CLJ ppt),初值为val. 其实结点如果是复制的结点(即代码中nq)的话初值应该是原结点的right?..没关系,我们总会更新到的 那么我们就有了两种做法:1.每次插入完暴力往上更新父亲结点的ri

UVA 12206 - Stammering Aliens(后缀数组)

UVA 12206 - Stammering Aliens 题目链接 题意:给定一个序列,求出出现次数大于m,长度最长的子串的最大下标 思路:后缀数组,搞出height数组后,利用二分去查找即可 这题之前还写过hash的写法也能过,不过写后缀数组的时候,犯了一个傻逼错误,把none输出成node还一直找不到...这是刷题来第二次碰到这种逗比错误了,还是得注意.. 代码: #include <cstdio> #include <cstring> #include <algori

POJ 3882 Stammering Aliens 后缀数组height应用

题目来源:POJ 3882 Stammering Aliens 题意:给你m一个一个字符串 求至少出现m次的最长字符串 可以在字符串中重叠出现 思路:二分长度l 然后从height数组中找长度大于等于l的前缀 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 40010; char s[maxn]; int sa[maxn]; i

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符.然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstrin

HDU4080Stammering Aliens(后缀数组+二分)

However, all efforts to decode their messages have failed so far because, as luck would have it, they have stumbled upon a race of stuttering aliens! Her team has found out that, in every long enough message, the most important words appear repeated

uva 12206 - Stammering Aliens(哈希)

题目链接:uva 12206 - Stammering Aliens 题目大意:给出一个字符串,找出至少出现m次的最长子串. 解题思路:哈希算法,将每个后缀数组建立一个哈希值,每次二分长度判断,每次判断时将哈希值排序,计数即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ll; const int ma

后缀数组专题

后缀数组基本模板 ①倍增法(时间O(NlogN),空间O(N)) 1 #include<iostream> 2 using namespace std; 3 const int maxl = 100010; 4 char s[maxl]; 5 int totlen; 6 int r2[maxl], cc[maxl],SA[maxl], RANK[maxl], Height[maxl]; 7 //r2:以第二关键字对后缀排序所得的辅助数组 8 //cc:计数排序辅助数组 9 //RANK:RAN

后缀数组(至少重复k次的可重叠的最长重复子串)—— POJ 3882

对应POJ 题目:点击打开链接 Stammering Aliens Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all efforts to decode their m

Stammering Aliens

Time Limit: 2000MS   Memory Limit: 65536K       Description Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all efforts to decode their messages have failed so far because, as luck would have it, they have st