1. 题目描述
给定一个长为$n \in [1, 4000]$的字符串,求其中长度最长的子串,并且该子串在原串中出现至少$m$次,并求最右起始位置。

2. 基本思路
两种方法:二分+后缀数组,或者二分+哈希。
(1) 二分+后缀数组
对子串长度进行二分,若不同后缀的公共前缀超过这个值,则对计数值累加。若计数值超过m,则证明这个公共前缀是有效的,计数过程中同时维护pos(最右边界),从而更新rpos。

(2)二分+哈希
仍然是对长度进行二分,然后枚举其实位置计算该长度的子串的哈希值,排序后,计算,超过m表示是有效的子串,从而更新最右位置。哈希采用LCP哈希。

3. 代码
(1)后缀数组

 /* 4080 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 const int maxn = ;
char s[maxn];
int a[maxn];
int height[maxn], sa[maxn], rrank[maxn];
int wa[maxn], wb[maxn], wc[maxn], wv[maxn];
int rpos, m; bool cmp(int *r, int a, int b, int l) {
return r[a]==r[b] && r[a+l]==r[b+l];
} void da(int *r, int *sa, int n, int m) {
int i, j, *x=wa, *y=wb, *t, p; for (i=; i<m; ++i) wc[i] = ;
for (i=; i<n; ++i) wc[x[i]=r[i]]++;
for (i=; i<m; ++i) wc[i] += wc[i-];
for (i=n-; i>=; --i) sa[--wc[x[i]]] = i;
for (j=,p=; p<n; j*=, m=p) {
for (p=, i=n-j; i<n; ++i) y[p++] = i;
for (i=; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i=; i<n; ++i) wv[i] = x[y[i]];
for (i=; i<m; ++i) wc[i] = ;
for (i=; i<n; ++i) wc[wv[i]]++;
for (i=; i<m; ++i) wc[i] += wc[i-];
for (i=n-; i>=; --i) sa[--wc[wv[i]]] = y[i];
for (t=x,x=y,y=t,x[sa[]]=,p=,i=; i<n; ++i)
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p- : p++;
}
} void calheight(int *r, int *sa, int n) {
int i, j, k = ; for (i=; i<=n; ++i) rrank[sa[i]] = i;
for (i=; i<n; height[rrank[i++]]=k)
for (k?k--:, j=sa[rrank[i]-]; r[j+k]==r[i+k]; ++k) ;
} void printSa(int n) {
for (int i=; i<=n; ++i)
printf("%d ", sa[i]);
putchar('\n');
} void printHeight(int n) {
for (int i=; i<=n; ++i)
printf("%d ", height[i]);
putchar('\n');
} bool judge(int bound, int n) {
int cnt = , pos = -; rpos = -;
rep(i, , n+) {
if (height[i] >= bound) {
pos = max(pos, sa[i]);
++cnt;
} else {
if (cnt >= m)
rpos = max(pos, rpos);
pos = sa[i];
cnt = ;
}
}
if (cnt >= m)
rpos = max(pos, rpos); return rpos!=-;
} void solve() {
int n; for (int i=; ; ++i) {
if (s[i] == '\0') {
n = i;
break;
}
a[i] = s[i] - 'a' + ;
}
a[n] = ;
if (m == ) {
printf("%d 0\n", n);
return ;
} da(a, sa, n+, );
calheight(a, sa, n); int l = , r = n, mid;
int ans = , ansp; while (l <= r) {
mid = (l + r) >> ;
if (judge(mid, n)) {
ans = mid;
ansp = rpos;
l = mid + ;
} else {
r = mid - ;
}
} if (ans)
printf("%d %d\n", ans, ansp);
else
puts("none");
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif while (scanf("%d", &m)!=EOF && m) {
scanf("%s", s);
solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}

(2)哈希

 /* 4080 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 #define ULL unsigned __int64 const int MOD = ;
const int maxn = ;
ULL H[maxn], base[maxn];
ULL Hash[maxn];
int pos[maxn];
char s[maxn];
int c[];
int m, len;
int rp; void init() {
base[] = ;
rep(i, , maxn)
base[i] = base[i-] * MOD;
} bool comp(const int& a, const int& b) {
if (Hash[a] == Hash[b])
return a<b;
return Hash[a] < Hash[b];
} bool judge(int l) {
int n = len - l + ;
for (int i=; i<n; ++i) {
pos[i] = i;
Hash[i] = H[i] - H[i+l] * base[l];
} sort(pos, pos+n, comp); int i = ;
rp = -;
while (i < n) {
int j = i++;
while (i<n && Hash[pos[i]]==Hash[pos[j]])
++i;
if (i-j >= m)
rp = max(rp, pos[i-]);
} return rp >= ;
} void solve() {
len = strlen(s) ; memset(c, , sizeof(c));
rep(i, , len)
++c[s[i]-'a'];
H[len] = ;
per(i, , len)
H[i] = H[i+] * MOD + s[i]-'a'; bool flag = false; rep(i, , ) {
if (c[i] >= m) {
flag = true;
break;
}
} if (!flag) {
puts("none");
return ;
} int ans = , ansp = -;
int l = , r = len, mid; while (l <= r) {
mid = (l + r) >> ;
if (judge(mid)) {
ans = mid;
ansp = rp;
l = mid + ;
} else {
r = mid - ;
}
} printf("%d %d\n", ans, ansp);
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif init();
while (scanf("%d", &m)!=EOF && m) {
scanf("%s", s);
solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}

【HDOJ】4080 Stammering Aliens的更多相关文章

  1. 【HDOJ】4729 An Easy Problem for Elfness

    其实是求树上的路径间的数据第K大的题目.果断主席树 + LCA.初始流量是这条路径上的最小值.若a<=b,显然直接为s->t建立pipe可以使流量最优:否则,对[0, 10**4]二分得到 ...

  2. 【HDOJ】【3506】Monkey Party

    DP/四边形不等式 裸题环形石子合并…… 拆环为链即可 //HDOJ 3506 #include<cmath> #include<vector> #include<cst ...

  3. 【HDOJ】【3516】Tree Construction

    DP/四边形不等式 这题跟石子合并有点像…… dp[i][j]为将第 i 个点开始的 j 个点合并的最小代价. 易知有 dp[i][j]=min{dp[i][j] , dp[i][k-i+1]+dp[ ...

  4. 【HDOJ】【3480】Division

    DP/四边形不等式 要求将一个可重集S分成M个子集,求子集的极差的平方和最小是多少…… 首先我们先将这N个数排序,容易想到每个自己都对应着这个有序数组中的一段……而不会是互相穿插着= =因为交换一下明 ...

  5. 【HDOJ】【2829】Lawrence

    DP/四边形不等式 做过POJ 1739 邮局那道题后就很容易写出动规方程: dp[i][j]=min{dp[i-1][k]+w[k+1][j]}(表示前 j 个点分成 i 块的最小代价) $w(l, ...

  6. 【HDOJ】【3415】Max Sum of Max-K-sub-sequence

    DP/单调队列优化 呃……环形链求最大k子段和. 首先拆环为链求前缀和…… 然后单调队列吧<_<,裸题没啥好说的…… WA:为毛手写队列就会挂,必须用STL的deque?(写挂自己弱……s ...

  7. 【HDOJ】【3530】Subsequence

    DP/单调队列优化 题解:http://www.cnblogs.com/yymore/archive/2011/06/22/2087553.html 引用: 首先我们要明确几件事情 1.假设我们现在知 ...

  8. 【HDOJ】【3068】最长回文

    Manacher算法 Manacher模板题…… //HDOJ 3068 #include<cstdio> #include<cstring> #include<cstd ...

  9. 【HDOJ】【1512】Monkey King

    数据结构/可并堆 啊……换换脑子就看了看数据结构……看了一下左偏树和斜堆,鉴于左偏树不像斜堆可能退化就写了个左偏树. 左偏树介绍:http://www.cnblogs.com/crazyac/arti ...

随机推荐

  1. ios技术面试题

    1.Difference between shallow copy and deep copy? 浅复制 只拷贝地址 不拷贝地址指向的对象 深复制 拷贝地址 并且指向拷贝的新对象 2.What is ...

  2. 活动图 Activity Diagram

    活动图 可通过一系列操作将业务流程或软件进程以工作流的形式显示出来.这些操作可以由人.软件组件或计算机来执行. 使用活动图可以描述多种类型的流程,如下: 1.用户和您的系统之间的业务流程或工作流. 2 ...

  3. 20145120 《Java程序设计》第5周学习总结

    20145120 <Java程序设计>第5周学习总结 教材学习内容总结 try和catch语法,如果被try{}的语句出现了catch()的问题就执行catch{}的语句. 错误的对象都继 ...

  4. 20145120 《Java程序设计》实验一实验报告

    20145120 <Java程序设计>实验一实验报告 实验名称:Java开发环境的熟悉 实验目的与要求: 1.使用JDK编译.运行简单的Java程序:(第1周学习总结) 2.编辑.编译.运 ...

  5. Java 8 VM GC Tunning Guide Charter 7-8-b

    第七章 并发gc Java 8提供两种并发gc,CMS和G1 Concurrent Mark Sweep (CMS) Collector This collector is for applicati ...

  6. Openmeeting 网页打开缓慢,视频卡的一个解决方法

    在初次安装完openmeeting以后,从浏览器打开后发现网页缓慢,视频有卡顿的现象. 原因:为openmeeting分配的内存太小. 解决方法: 找到根目录的red5.bat,打开后查找“set J ...

  7. 一个简单的PHP登录演示(SESSION版 与 COOKIE版)

    //==============COOKIE版本的简单登录================ if ($_GET[out]){ setcookie('id',''); setcookie('pw','' ...

  8. 【锋利的JQuery-学习笔记】添加提示图片

    效果图: hot图片: (注意:这个图标本身就有抖动效果的,并不是由于标签<del>而具有抖动效果) 周期性抖动,起到提示的作用 html: <div class="jnC ...

  9. MethodInvoker 委托

    MethodInvoker 提供一个简单委托,该委托用于调用含 void 参数列表的方法. 在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托. 下面的代码示例演 ...

  10. PHP 开发中的外围资源性能分析(二)

    暂且不讨论「PHP 是不是最好的编程语言」,本文我们将分别分析一下在 PHP 程序的后端外围资源和前端外围资源,它们对整个 PHP Web 应用体验的影响,这往往比语言本身大得多. 上一篇中我们分析了 ...