zoukankan      html  css  js  c++  java
  • [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 ? ' ' : '
    ');
    		for(int i = 1; i <= n; i++) printf("%d%c", height[i], i < 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('
    ');
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    angular组件开发
    APICloud案例源码、模块源码、考试源码、开发工具大集合!赶快收藏
    Vue-router实现单页面应用在没有登录情况下,自动跳转到登录页面
    原生js实现架子鼓特效
    A Beginner’s Introduction to CSS Animation中文版
    react开发教程(三)组件的构建
    体验javascript之美第五课 五分钟彻底明白 匿名函数自执行和闭包
    这些例子很炫,感兴趣的童鞋可以了解一下
    体验javascript之美6:如果你觉得什么都会了或者不知道js学什么了看这里-面向对象编程
    傅里叶变换,小波变换,EMD,HHT,VMD(经典和现代信号处理方法基本原理概念)
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6514034.html
Copyright © 2011-2022 走看看