UVA 12206 Stammering Aliens(基于哈希值的LCP算法)
来源:互联网 发布:哪个网络机顶盒好用 编辑:程序博客网 时间:2024/05/16 17:38
UVA 12206 Stammering Aliens(基于哈希值的LCP算法)
题意:给你一个字符串s和m,求出字符串中至少出现m次的最长子串.如果有多解,输出最长字符串的长度以及它出现的最大位置.
分析:其实本题可以用后缀数组来解.下面用哈希值来做.详见刘汝佳训练指南P225
首先对于一个长为n的字符串,我们定义它的哈希值为(下面的x值是人为设定的一个值):
s[0]+s[1]*x+s[2]*x^2+…s[n-1]*x^(n-1)
那么它的每个后缀[i,n-1]的哈希值为H[i]:
s[i]+s[i+1]*x+…s[n-1]*x^(n-1-i)
由上可以得到递推关系:
H[n]=0;
H[i]=H[i+1]*x+s[i]
那么对于该串s中的任意一段的哈希值为hash[i,L]:
hash[i,L]=s[i]+s[i+1]*x+s[i+2]*x^2+…s[i+L-1]*x^(L-1)=H[i]-H[i+L]*x^L
(验证一下上面的公式,看看是不是.其实主要是明白一段连续字符串的哈希值如何计算就可以,其他的递推公式是为了加快我们计算的.)
在程序中,我们二分答案,一一试探看看所有长度为l的子串中有没有出现m次的.我们只需要求出长度为l的所有子串的哈希值,然后将该哈希值数组排序,然后从小到大扫描,看看有没有同一个哈希值连续出现了m次的,如果有就表示长度l可以,并且记下该串最后出现的位置pos即可.
程序中我们用unsighed long long里保存哈希值,如果数据太大就自动溢出了,对于不同长度的串具有同一个哈希值的可能行很小很小.如果不放心还可以改变x的值再计算一次看看两者的哈希值是否相同,如果还是相同,那么出错的可能性就更小了.
AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 40000+1000;typedef unsigned long long LL;LL h[maxn],x;//后缀哈希值char str[maxn];int n,m,max_pos;LL mi[maxn];//mi[i]的值是x的i次方的值struct node{ LL hash;//起点为pos且长len的串的哈希值 int pos;//起点位置 bool operator <(const node &b)const { return hash<b.hash ||(hash==b.hash && pos<b.pos); }}nodes[maxn];bool check(int len){ for(int i=0;i+len-1<=n-1;i++)//共有n-len+1个长为len的连续子串 { nodes[i].hash=h[i]-h[i+len]*mi[len]; nodes[i].pos=i;//起点位置 } sort(nodes,nodes+n-len+1); max_pos=-1; int sum=0; for(int i=0;i+len-1<=n-1;i++) { if(i==0 || nodes[i].hash==nodes[i-1].hash) { sum++; if(sum>=m) max_pos=max(max_pos,nodes[i].pos); } else sum=1; } return max_pos>=0;}int main(){ x=123; while(scanf("%d",&m)==1&&m) { scanf("%s",str); n=strlen(str); h[n]=0; for(int i=n-1;i>=0;i--) h[i]=h[i+1]*x+str[i]-'a'; mi[0]=1; for(int i=1;i<=n;i++) mi[i]=mi[i-1]*x; if(!check(1)) { printf("none\n"); continue; } int min=1,max=n; while(min<max) { int mid=min+(max-min+1)/2; if(check(mid)) min=mid; else max=mid-1; } check(min); printf("%d %d\n",min,max_pos); } return 0;}
- UVA 12206 Stammering Aliens(基于哈希值的LCP算法)
- UVA 12206 - Stammering Aliens(Hash+LCP)
- uvalive 4513 Stammering Aliens (基于Hash的LCP+二分)
- uva 12206 - Stammering Aliens(哈希)
- UVA - 12206 Stammering Aliens (hash)
- 重复出现超过m次的最长的子串的最大下标 后缀数组或Hash+LCP UVA 12206 - Stammering Aliens
- UVA 12206 - Stammering Aliens(后缀数组)
- UVA 12206 Stammering Aliens(后缀数组+二分)
- UVA 12206 Stammering Aliens(字符串hash)
- 【Hash求LCP】HDU4080[Stammering Aliens]题解
- Uva LA 4513 Stammering Aliens(Follow the example, solve by lcp using hash)
- 后缀数组,LCP(Stammering Aliens,LA 4513)
- LA 4513(Stammering Aliens-Hash求LCP)[Template:hash求LCP]
- uva12206 - Stammering Aliens 哈希LCP和后缀数组两种做法
- 2014北京邀请赛 J 题 基于哈希值的LCP算法
- zoj 3395 Stammering Aliens
- LA 4513 Stammering Aliens
- HDOJ 4080 Stammering Aliens
- QT学习(一)
- 接收大文件(ios)
- 余额宝操盘手:我们不会崩盘滴
- 链表
- UItextFile常用操作设置
- UVA 12206 Stammering Aliens(基于哈希值的LCP算法)
- 浅谈我对“活在当下”的理解
- 二叉树
- 发帖测试2.3
- UVa 11178 Morley's Theorem(几何)
- Python快速学习08:模块的操作
- Cache的设计和实现 LRU Cache
- 【并查集 偏移量】HDU 1829 A Bug's Life
- sublime利用ClosureCompiler和YUICompressor本地压缩