题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的。

析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2].....这些点中相邻的两个,然后向前和向后匹配,

看看最大的匹配多大,然后把所有的答案记录下来,最后再从sa中开始枚举答案,第一个就是字典序最小的。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e16;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
} struct Array{
int sa[maxn], s[maxn], t[maxn], t2[maxn];
int r[maxn], h[maxn], c[maxn], dp[maxn][20];
int n; void init(){
n = 0; memset(sa, 0, sizeof sa);
} void build_sa(int m){
int *x = t, *y = t2;
for(int i = 0; i < m; ++i) c[i] = 0;
for(int i = 0; i < n; ++i) ++c[x[i] = s[i]];
for(int i = 1; i < m; ++i) c[i] += c[i-1];
for(int i = n-1; i >= 0; --i) sa[--c[x[i]]] = i; for(int k = 1; k <= n; k <<= 1){
int p = 0;
for(int i = n-k; i < n; ++i) y[p++] = i;
for(int i = 0; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k;
for(int i = 0; i < m; ++i) c[i] = 0;
for(int i = 0; i < n; ++i) ++c[x[y[i]]];
for(int i = 1; i < m; ++i) c[i] += c[i-1];
for(int i = n-1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; swap(x, y);
p = 1; x[sa[0]] = 0;
for(int 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 getHight(){
int k = 0;
for(int i = 0; i < n; ++i) r[sa[i]] = i;
for(int i = 0; i < n; ++i){
if(k) --k;
int j = sa[r[i]-1];
while(s[i+k] == s[j+k]) ++k;
h[r[i]] = k;
}
} void rmq_init(){
for(int i = 1; i <= n; ++i) dp[i][0] = h[i];
for(int j = 1; (1<<j) <= n; ++j)
for(int i = 1; i + (1<<j) <= n; ++i)
dp[i][j] = min(dp[i][j-1], dp[i+(1<<j-1)][j-1]);
} int query(int L, int R){
L = r[L]; R = r[R];
if(L > R) swap(L, R);
++L;
int k = log(R-L+1) / log(2.0);
return min(dp[L][k], dp[R-(1<<k)+1][k]);
}
};
Array arr;
char s[maxn];
vector<int> v; int main(){
int kase = 0;
while(scanf("%s", s) == 1 && s[0] != '#'){
n = strlen(s);
arr.init();
for(int i = 0; i < n; ++i)
arr.s[arr.n++] = s[i] - 'a' + 1;
arr.s[arr.n++] = 0;
arr.build_sa(30);
arr.getHight();
arr.rmq_init();
int ans = 0;
for(int i = 1; i <= n; ++i)
for(int j = 0; j + i <= n; j += i){
int k = arr.query(j, j+i);
int res = k / i + 1;
int t = j - (i - k % i);
if(t >= 0 && arr.query(t, t + i) >= k) ++res;
if(ans < res){
ans = res;
v.clear();
v.push_back(i);
}
else if(ans == res) v.push_back(i);
} printf("Case %d: ", ++kase);
bool ok = true;
for(int i = 0; i < n && ok; ++i)
for(int j = 0; j < v.size() && ok; ++j)
if(arr.sa[i] + v[j] <= n){
if(arr.query(arr.sa[i], arr.sa[i] + v[j]) + v[j] >= ans * v[j]){
ok = false;
for(int k = arr.sa[i], l = 0; l < ans * v[j]; ++l, ++k)
putchar(s[k]);
printf("\n");
}
}
}
return 0;
}

  

POJ 3693 Maximum repetition substring (后缀数组+RMQ)的更多相关文章

  1. POJ 3693 Maximum repetition substring ——后缀数组

    重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...

  2. poj 3693 Maximum repetition substring (后缀数组)

    其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...

  3. poj3693 Maximum repetition substring (后缀数组+rmq)

    Description The repetition number of a string is defined as the maximum number R such that the strin ...

  4. POJ3693 Maximum repetition substring 后缀数组

    POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...

  5. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

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

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10461   Ac ...

  7. Maximum repetition substring 后缀数组

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7578   Acc ...

  8. POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS   Memory Li ...

  9. POJ 3693 Maximum repetition substring(后缀数组)

    Description The repetition number of a string is defined as the maximum number R such that the strin ...

随机推荐

  1. [算法]Evaluate Reverse Polish Notation

    Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...

  2. HDU1232 畅通工程,并查集

    这里要补充一些知识点,并查集三操作 1.找到父节点递归写法int Findf(int x){ if(father[x]!=x) father[x]=Findf(father[x]); return f ...

  3. App开发流程之创建项目和工程基本配置

    我的开发环境为:Mac OS X EI Capitan(10.11.6),Xcode 7.3.1 首先说明一下这个项目的初衷,我并非要创建一个完整的上架应用,旨在创建一个可运行的,通用配置.架构,提供 ...

  4. php设计模式课程---6、策略模式如何使用

    php设计模式课程---6.策略模式如何使用 一.总结 一句话总结:比如代码需求,做一饭店,有南北方不同菜系,不同分店有不同的饭菜汤的需求,代码怎么设计 从饭店有特色过渡到厨师有特色(南方厨师(南方饭 ...

  5. PHP消息队列用法实例分析

    这篇文章主要介绍了PHP消息队列用法,结合实例形式分析了PHP消息队列用于Linux下进程间通信的相关技巧,需要的朋友可以参考下   该消息队列用于linux下,进程通信 队列状态信息:具体参考手册

  6. jQuery 参考手册 - 选择器

    jQuery 选择器 选择器 实例 选取 * $("*") 所有元素 #id $("#lastname") id="lastname" 的元 ...

  7. 为什么jdk1.8不支持sql.append,该如何解决

    StringBuilder sql = new StringBuilder("SELECT ID,COMMAND,DESCRIPTION,CONTENT FROM message where ...

  8. MicroMessage的动态操作(第二步)

    现在开始将静态页面转化成动态页面.将页面上的信息转化成 数据库提供的信息. 建立jdbc获取数据库连接,并设置一个查询sql语句,查出所有结果.但是因为查询结果rs包含全表信息,是多行. 为了保存查询 ...

  9. codeforces 631A A. Interview

    A. Interview time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  10. 设计模式 之 《观察者模式 (Observer)》

    #ifndef __OBSERVER_MODEL__ #define __OBSERVER_MODEL__ #include <string> #include <iostream& ...