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];
int t[maxn], t2[maxn], c[maxn];
int rank[maxn], height[maxn];
int pos, lim;
void build_sa(int m, int n)
{
	int i, *x = t, *y = t2;
	for(i = 0; i < m; i++)
		c[i] = 0;
	for(i = 0; i < n; i++)
		c[x[i] = s[i]]++;
	for(i = 1; i < m; i++)
		c[i] += c[i-1];
	for(i = n-1; i >= 0; i--)
		sa[--c[x[i]]] = i;
	for(int k = 1; k <= n; k <<= 1)
	{
		int p = 0;
		for(i = n-k; i < n; i++)
			y[p++] = i;
		for(i = 0; i < n; i++)
			if(sa[i] >= k)
				y[p++] = sa[i] - k;
		for(i = 0; i < m; i++)
			c[i] = 0;
		for(i = 0; i < n; i++)
			c[x[y[i]]]++;
		for(i = 0; i < m; i++)
			c[i]+= c[i-1];
		for(i = n-1; i >= 0; i--)
			sa[--c[x[y[i]]]] = y[i];
		swap(x,y);
		p = 1; x[sa[0]] = 0;
		for(i = 1; i < n; i++)
			x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
		if(p >= n)
			break;
		m = p;
	}
}

void getHeight(int n)
{
	int k = 0;
	for(int i = 0; i <= n; i++)
		rank[sa[i]] = i;
	for(int i = 0; i < n; i++)
	{
		if(k)
			k--;
		int j = sa[rank[i]-1];
		while(s[i+k] == s[j+k])
			k++;
		height[rank[i]] = k;
	}
}

bool ok(int l, int n)
{
	int flag = 0;
	int cnt = 1;
	pos = 0;
	int p = -1;
	for(int i = 1; i <= n; i++)
	{
		if(height[i] >= l)
		{
			cnt++;
			p = max(p, sa[i]);
		}
		else
		{

			p = sa[i];
			cnt = 1;
		}

		if(cnt >= lim)
		{
			flag = 1;
			pos = max(pos, p);
		}
	}
	if(flag)
		return true;
	return false;
}
int main()
{
	int l, r, n;
	while(scanf("%d", &lim) && lim)
	{
		scanf("%s", s);
		n = strlen(s);
		if(lim == 1)
		{
			printf("%d 0\n", n);
			continue;
		}
		l = 1;
		r = n;
		int ans = -1;
		int ans2;
		build_sa(256, n+1);
		getHeight(n);

		while(l <= r)
		{
			int m = (l + r) >> 1;

			if(ok(m, n))
			{
				ans = m;
				ans2 = pos;
				l = m+1;
			}
			else
				r = m-1;
		}

		if(ans == -1)
			puts("none");
		else
		{
			printf("%d %d\n", ans, ans2);
		}

	}
	return 0;

}

POJ 3882 Stammering Aliens 后缀数组height应用,码迷,mamicode.com

时间: 2024-10-05 01:31:52

POJ 3882 Stammering Aliens 后缀数组height应用的相关文章

UVA 12206 - Stammering Aliens(后缀数组)

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

POJ 3294 Life Forms (后缀数组)

题目大意: 求出在m个串中出现过大于m/2次的子串. 思路分析: 如果你只是直接跑一次后缀数组,然后二分答案扫描的话. 那么就试一下下面这个数据. 2 abcdabcdefgh efgh 这个数据应该输出 efgh 问题就在于对于每一个串,都只能参与一次计数,所以在check的时候加一个标记数组是正解. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring>

POJ - 1743 后缀数组 height分组

题意:求最长不可重叠的相同差值子串的长度 这道题算是拖了好几个月,现在花了点时间应该搞懂了不少,尝试分析一下 我们首先来解决一个退化的版本,求最长不可重叠的相同子串(差值为0) 比如\(aabaabaa\), 那么所求的子串有\(aab,aba,baa\)三个 如何求?不妨枚举.枚举是否有长度为\(k\)的最长不可重叠相同子串 可是后缀数组中并不能直接表示出子串,只能间接地用后缀来表示 长度为\(k\)的相同子串\(=>\)最大公共前缀长度为\(k\)的子串\(=>\)最大公共前缀长度大于等于

poj 3261 Milk Patterns 后缀数组+二分

1 /*********************************************************** 2 题目: Milk Patterns(poj 3261) 3 链接: http://poj.org/problem?id=3261 4 题意: 给一串数字,求这些数字中公共子串个数大于k的 5 最长串. 6 算法: 后缀数组+二分 7 ***********************************************************/ 8 #incl

POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It

poj 2406 Power Strings 后缀数组解法

连续重复子串问题 poj 2406 Power Strings http://poj.org/problem?id=2406 问一个串能否写成a^n次方这种形式. 虽然这题用kmp做比较合适,但是我们还是用后缀数组做一做,巩固后缀数组的能力. 对于一个串,如果能写出a^n这种形式,我们可以暴力枚举循环节长度L,那么后缀suffix(1)和suffix(1 + L)的LCP应该就是 lenstr - L.如果能满足,那就是,不能,就不是. 这题的话da算法还是超时,等我学了DC3再写上来. 其实这

Poj 3294 Life Forms (后缀数组 + 二分 + Hash)

题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的height.然后二分答案串的长度K,根据K把新文本串的后缀串分块,统计每块中的原文本串出现的次数,大于原文本串数目的一半就作为答案记录下来,对于输出字典序,height就是排好序的后缀数组,只要按照顺序输出即可. 1 #include <cstdio> 2 #include <cstring>

POJ 2406 Power String 后缀数组

这题曾经用KMP做过,用KMP 做非常的简单,h函数自带的找循环节功能. 用后缀数组的话,首先枚举循环节长度k,然后比较LCP(suffix(k + 1), suffix(0)) 是否等于len - k, 如果相等显然k就是一个循环节. 得到LCP的话可以通过预处理出所有点和0的lcp就好了.另外倍增法构造后缀数组还有用RMQ来搞lcp nlogn是不行的,会超时,所以可以dc3走起了.. #include <cstdio> #include <cstring> #include

poj 1743 Musical Theme(后缀数组)

Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30544   Accepted: 10208 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the