[POJ3693]Maximum repetition substring

Posted xjr_01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POJ3693]Maximum repetition substring相关的知识,希望对你有一定的参考价值。

[POJ3693]Maximum repetition substring

试题描述

The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.

Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.

输入

The input consists of multiple test cases. Each test case contains exactly one line, which
gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.

The last test case is followed by a line containing a ‘#‘.

输出

For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.

输入示例

ccabababc
daabbccaa
#

输出示例

Case 1: ababab
Case 2: aa

数据规模及约定

见“输入

题解

这题好神。。。

注意到如果存在一个子串是由长度为 L 的串重复得来,那么我们每隔 L 取一个字符一定能取到所有周期中的一个字符。这样的话就可以利用调和级数枚举 L 的大小,然后取 L 的整倍数的位置,然后再统计统计更新更新就好了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>

#define maxn 200010
#define maxlog 20

int Log[maxn];

struct Suf {
	char S[maxn];
	int n, rank[maxn], height[maxn], sa[maxn], Ws[maxn];
	int mnr[maxlog][maxn], mnh[maxlog][maxn];
	
	Suf() {}
	void init(const char* Str) {
		memset(S, 0, sizeof(S));
		strcpy(S + 1, Str);
		n = strlen(S + 1);
	}
	
	bool cmp(int* a, int p1, int p2, int l) {
		if(p1 + l > n && p2 + l > n) return a[p1] == a[p2];
		if(p1 + l > n || p2 + l > n) return 0;
		return a[p1] == a[p2] && a[p1+l] == a[p2+l];
	}
	
	void ssort() {
		int *x = rank, *y = height;
		int m = 0;
		memset(Ws, 0, sizeof(Ws));
		for(int i = 1; i <= n; i++) Ws[x[i] = S[i]]++, m = std::max(m, x[i]);
		for(int i = 1; i <= m; i++) Ws[i] += Ws[i-1];
		for(int i = n; i; i--) sa[Ws[x[i]]--] = i;
		for(int j = 1, pos = 0; pos < n; j <<= 1, m = pos) {
			pos = 0;
			for(int i = n - j + 1; i <= n; i++) y[++pos] = i;
			for(int i = 1; i <= n; i++) if(sa[i] > j) y[++pos] = sa[i] - j;
			for(int i = 1; i <= m; i++) Ws[i] = 0;
			for(int i = 1; i <= n; i++) Ws[x[i]]++;
			for(int i = 1; i <= m; i++) Ws[i] += Ws[i-1];
			for(int i = n; i; i--) sa[Ws[x[y[i]]]--] = y[i];
			std::swap(x, y); pos = 1; x[sa[1]] = 1;
			for(int i = 2; i <= n; i++) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? pos : ++pos;
		}
		return ;
	}
	
	void calch() {
		for(int i = 1; i <= n; i++) rank[sa[i]] = i;
		for(int i = 1, j, k = 0; i <= n; height[rank[i++]] = k)
			for(k ? k-- : 0, j = sa[rank[i]-1]; S[j+k] == S[i+k]; k++);
		return ;
	}
	
	void debug() {
		for(int i = 1; i <= n; i++) printf("%d%c", sa[i], i < n ? ‘ ‘ : ‘\n‘);
		for(int i = 1; i <= n; i++) printf("%d%c", height[i], i < n ? ‘ ‘ : ‘\n‘);
		return ;
	}
	
	void rmq_init() {
		Log[1] = 0;
		for(int i = 2; i <= n; i++) Log[i] = Log[i>>1] + 1;
		for(int i = 1; i <= n; i++) mnr[0][i] = rank[i], mnh[0][i] = height[i];
		for(int j = 1; (1 << j) <= n; j++)
			for(int i = 1; i + (1 << j) - 1 <= n; i++) {
				mnr[j][i] = std::min(mnr[j-1][i], mnr[j-1][i+(1<<j-1)]);
				mnh[j][i] = std::min(mnh[j-1][i], mnh[j-1][i+(1<<j-1)]);
			}
		return ;
	}
	
	int qrnk(int l, int r) {
		int t = Log[r-l+1];
		return std::min(mnr[t][l], mnr[t][r-(1<<t)+1]);
	}
	
	int qhei(int l, int r) {
		if(l > r) std::swap(l, r); l++;
		int t = Log[r-l+1];
		return std::min(mnh[t][l], mnh[t][r-(1<<t)+1]);
	}
} sol1, sol2;

char inS[maxn];

int main() {
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	int kase = 0;
	while(~scanf("%s", inS)) {
		if(inS[0] == ‘#‘) break;
		sol1.init(inS);
		for(int i = 0; i < (sol1.n >> 1); i++) std::swap(inS[i], inS[sol1.n-i-1]);
		sol2.init(inS);
		
		int n = sol1.n;
		sol1.ssort(); sol1.calch(); sol1.rmq_init();
		sol2.ssort(); sol2.calch(); sol2.rmq_init();
//		sol1.debug(); sol2.debug();
		int st = sol1.sa[sol1.qrnk(1,n)], len = 1, rpt = 1;
		for(int L = 1; L <= n; L++) {
			for(int i = L; i + L <= n; i += L) {
				if(sol1.S[i] == sol1.S[i+L]) {
					int r = sol1.qhei(sol1.rank[i], sol1.rank[i+L]) - 1,
						l = sol2.qhei(sol2.rank[n-i+1], sol2.rank[n-i-L+1]) - 1,
						tmp = r / L + 1 + l / L + 1;
					if(rpt < tmp) rpt = tmp, st = sol1.sa[sol1.qrnk(i-l,i-l+(l+r+1)%L)], len = rpt * L;
					else if(rpt == tmp) {
						int pos = sol1.sa[sol1.qrnk(i-l,i-l+(l+r+1)%L)];
						if(sol1.rank[st] > sol1.rank[pos]) st = pos, len = rpt * L;
					}
				}
			}
		}
		
		printf("Case %d: ", ++kase);
		for(int i = st; i <= st + len - 1; i++) putchar(sol1.S[i]); putchar(‘\n‘);
	}
	
	return 0;
}

 

以上是关于[POJ3693]Maximum repetition substring的主要内容,如果未能解决你的问题,请参考以下文章

POJ3693Maximum repetition substring (后缀数组+RMQ)(占位)

POJ3693 Maximum repetition substring

POJ 3693 Maximum repetition substring(最多重复次数的子串)

POJ 3693 Maximum repetition substring(后缀数组[重复次数最多的连续重复子串])

POJ 3693 Maximum repetition substring(后缀数组[重复次数最多的连续重复子串])

POJ 3693 Maximum repetition substring(后缀数组[重复次数最多的连续重复子串])