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

【思路】

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

法一:

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

法二:

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

    法三:(UPD.16/4/6)

     SAM。求|right|。

注意划分height一定要精确且如果m=1需要特判

【代码1】

 //193ms
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int maxn = +; int s[maxn];
int sa[maxn],c[maxn],t[maxn],t2[maxn];
void build_sa(int m,int n) {
int i,*x=t,*y=t2;
for(i=;i<m;i++) c[i]=;
for(i=;i<n;i++) c[x[i]=s[i]]++;
for(i=;i<m;i++) c[i]+=c[i-];
for(i=n-;i>=;i--) sa[--c[x[i]]]=i;
for(int k=;k<=n;k<<=) {
int p=;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=;i<m;i++) c[i]=;
for(i=;i<n;i++) c[x[y[i]]]++;
for(i=;i<m;i++) c[i]+=c[i-];
for(i=n-;i>=;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=; x[sa[]]=;
for(i=;i<n;i++)
x[sa[i]]=y[sa[i]]==y[sa[i-]] && y[sa[i]+k]==y[sa[i-]+k]?p-:p++;
if(p>=n) break;
m=p;
}
}
int rank[maxn],height[maxn];
void getHeight(int n) {
int i,j,k=;
for(i=;i<=n;i++) rank[sa[i]]=i;
for(i=;i<n;i++) {
if(k) k--;
j=sa[rank[i]-];
while(s[j+k]==s[i+k]) k++;
height[rank[i]]=k;
}
}
int limit,n,pos;
bool can(int L) { //一定要注意划分height数组的准确性
pos=-;
int cnt=,mx=sa[];
for(int i=;i<=n;i++) {
mx=max(mx,sa[i]);
if(height[i]<L) cnt=,mx=sa[i];
else {
if(++cnt>=limit) pos=max(pos,mx);
}
}
return pos>=;
} char expr[maxn];
int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
while(scanf("%d",&limit)== && limit) {
scanf("%s",expr);
n=strlen(expr);
for(int i=;i<n;i++) s[i]=expr[i]; s[n]=; build_sa('z'+,n+);
getHeight(n); if(limit==) { printf("%d 0\n",n); continue; }
int L=,R=n+;
while(L<R) {
int M=L+(R-L+)/;
if(can(M)) L=M; else R=M-;
}
if(!can(L)) printf("none\n");
else printf("%d %d\n",L,pos);
}
return ;
}

da

【代码2】

 //1628ms
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; typedef unsigned long long ULL;
const int maxn = +;
const int x = ; ULL hash[maxn],xp[maxn],H[maxn];
int m,n;
char s[maxn]; int cmp(const int& a,const int& b) {
return hash[a]<hash[b] || (hash[a]==hash[b] && a<b);
}
int pos,rank[maxn];
bool can(int L) {
pos=-;
for(int i=;i<n-L+;i++) hash[i]=H[i]-H[i+L]*xp[L],rank[i]=i;
sort(rank,rank+n-L+,cmp);
int cnt=;
for(int i=;i<n-L+;i++) {
if(!i || hash[rank[i]]!=hash[rank[i-]]) cnt=;
if(++cnt>=m) pos=max(pos,rank[i]);
}
return pos>=;
} int main() {
//freopen("in.in","r",stdin);
//freopen("outr.out","w",stdout);
while(scanf("%d",&m)== && m) {
scanf("%s",s);
n=strlen(s); H[n]=,xp[]=;
for(int i=n-;i>=;i--) H[i]=H[i+]*x+s[i]-'a';
for(int i=;i<=n;i++) xp[i]=xp[i-]*x; if(!can()) printf("none\n");
else {
int L=,R=n+;
while(L<R) {
int M=L+(R-L+)/;
if(can(M)) L=M; else R=M-;
}
can(L);
printf("%d %d\n",L,pos);
}
}
return ;
}

hash

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

  1. HDU4080 Stammering Aliens(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...

  2. UVA 12206 - Stammering Aliens(后缀数组)

    UVA 12206 - Stammering Aliens 题目链接 题意:给定一个序列,求出出现次数大于m,长度最长的子串的最大下标 思路:后缀数组.搞出height数组后,利用二分去查找就可以 这 ...

  3. Uva12206 Stammering Aliens 后缀数组&&Hash

    Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all effort ...

  4. UVALive - 4513 Stammering Aliens ——(hash+二分 || 后缀数组加二分)

    题意:找一个出现了m次的最长子串,以及这时的最右的位置. hash的话代码还是比较好写的,,但是时间比SA多很多.. #include <stdio.h> #include <alg ...

  5. Hash(LCP) || 后缀数组 LA 4513 Stammering Aliens

    题目传送门 题意:训练指南P225 分析:二分寻找长度,用hash值来比较长度为L的字串是否相等. #include <bits/stdc++.h> using namespace std ...

  6. HDU4080Stammering Aliens(后缀数组+二分)

    However, all efforts to decode their messages have failed so far because, as luck would have it, the ...

  7. Stammering Aliens

    Stammering Aliens Time Limit: 2000MS   Memory Limit: 65536K       Description Dr. Ellie Arroway has ...

  8. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  9. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

随机推荐

  1. 表达式:使用API创建表达式树(2)

    一.BlockExpression类:表式一个包含可在其中定义变量的表达式序列的块.是一组表达式,类似于多个委托的 += 后的效果,其返回表达式是最后一个表达式决定.以下是BlockExpressio ...

  2. 查询两个日期(时间)以内的数据,between and 或 and 连>= <=,to_date()

    between and 方法 select * from kk.kkhmd where larq between(to_date('2008-9-3','yyyy-mm-dd')) and (to_d ...

  3. PropertyPlaceholderConfigurer的用法(使用spring提供的类读取数据库配置信息.properties)

    http://www.cnblogs.com/wanggd/archive/2013/07/04/3172042.html(写的很好)

  4. 一个Socket数据处理模型

    Socket编程中,如何高效地接收和处理数据,这里介绍一个简单的编程模型. Socket索引 - SocketId 在给出编程模型之前,先提这样一个问题,程序中如何描述Socket连接? 为什么这么问 ...

  5. jQuery 效果- 动画

    jQuery animate() 方法允许您创建自定义的动画. jQuery 动画实例 jQuery jQuery 动画 - animate() 方法 jQuery animate() 方法用于创建自 ...

  6. java_设计模式_适配器模式_Adapter Pattern(2016-08-09)

    概念 将一个接口转换成客户希望的另外一个接口.(该模式使得原本不兼容的类可以一起工作). UML图 适配器模式有类的适配器模式和对象的适配器模式两种不同的形式. (1)对象的适配器模式结构图 (2)类 ...

  7. 关于使用iframe标签自适应高度的使用

    在ifrome内设定最小高度,(此方法只适用于页面内切换高度不一.但是会保留最大高度,返回后保持最大高度不再回到最初页面的高度) <iframe id="one4" widt ...

  8. [转]iframe自适应宽度高度

    <iframe id="iframe" onLoad="AutoFit();" frameborder="0" scrolling=& ...

  9. python类class基础

              44.class类:                      一.类定义的一般形式:                            1.简单的形式:实例化对象没有自己独有 ...

  10. JS Math.sin() 与 Math.cos() 用法

    Math.sin(x)      x 的正玄值.返回值在 -1.0 到 1.0 之间: Math.cos(x)    x 的余弦值.返回的是 -1.0 到 1.0 之间的数: 这两个函数中的X 都是指 ...