SPOJ 687. Repeats(字尾陣列求最長重複子串)
題目大意:給你一個串讓你求出重複次數最多的連續重複子串的重複次數。
解題思路:論文上給出的解答是:
這還沒完,因為經過這兩個點的情況還不完備,應還可以假設起點在 [ i*j-i+1, i*j-d],其中 d = i-L/i (d = i-L%i)其意義為根據已知的匹配長度,可以將起點往前移動的範圍,太靠後將不能夠構造出比之前更好的解。如果要求出某個最多的連續重複子串的最小字典序子需要列舉所有起點,但如果只是要的到最多的重複次數或者任意最多的連續重複子串,那麼只需要列舉i*j-d處的起點即可,因為後面的起點若能夠得到最優的結果,那麼i*j-d處也一定能得到,且答案一樣均為L/i+2。(這樣保證了第0倍不是從起點開始的解的情況。)
SPOJ Problem Set (classical)687. RepeatsProblem code: REPEATS |
A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed string t with length l>=1. For example, the string
s = abaabaabaaba
is a (4,3)-repeat with t = aba as its seed string. That is, the seed string t is 3 characters long, and the whole string s is obtained by repeating t 4 times.
Write a program for the following task: Your program is given a long string u consisting of characters ‘a’ and/or ‘b’ as input. Your program must find some (k,l)-repeat that occurs as substring within u with k as large as possible. For example, the input string
u = babbabaabaabaabab
contains the underlined (4,3)-repeat s starting at position 5. Since u contains no other contiguous substring with more than 4 repeats, your program must output the maximum k.
Input
In the first line of the input contains H- the number of test cases (H <= 20). H test cases follow. First line of each test cases is n - length of the input string (n <= 50000), The next n lines contain the input string, one character (either ‘a’ or ‘b’) per line, in order.
Output
For each test cases, you should write exactly one interger k in a line - the repeat count that is maximized.
Example
Input: 1 17 b a b b a b a a b a a b a a b a b Output: 4since a (4, 3)-repeat is found starting at the 5th character of the input string.
Added by: | Hoang Hong Quan |
Date: | 2006-01-05 |
Time limit: | 1.985s |
Source limit: | 50000B |
Memory limit: | 1536MB |
Cluster: | Cube (Intel Pentium G860 3GHz) |
Languages: | All except: NODEJS PERL 6 SCM chicken VB.net |
Resource: | BOI 2004 |
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <map>
#include <set>
#define eps 1e-9
///#define M 1000100
///#define LL __int64
#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)
#define mod 1000000007
#define Read() freopen("autocomplete.in","r",stdin)
#define Write() freopen("autocomplete.out","w",stdout)
#define Cin() ios::sync_with_stdio(false)
using namespace std;
inline int read()
{
char ch;
bool flag = false;
int a = 0;
while(!((((ch = getchar()) >= '0') && (ch <= '9')) || (ch == '-')));
if(ch != '-')
{
a *= 10;
a += ch - '0';
}
else
{
flag = true;
}
while(((ch = getchar()) >= '0') && (ch <= '9'))
{
a *= 10;
a += ch - '0';
}
if(flag)
{
a = -a;
}
return a;
}
void write(int a)
{
if(a < 0)
{
putchar('-');
a = -a;
}
if(a >= 10)
{
write(a / 10);
}
putchar(a % 10 + '0');
}
const int maxn = 50050;
int wa[maxn], wb[maxn], wv[maxn], ws1[maxn];
int sa[maxn];
int 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, p, *x = wa, *y = wb;
for(i = 0; i < m; i++) ws1[i] = 0;
for(i = 0; i < n; i++) ws1[x[i] = r[i]]++;
for(i = 1; i < m; i++) ws1[i] += ws1[i-1];
for(i = n-1; i >= 0; i--) sa[--ws1[x[i]]] = i;
for(j = 1, p = 1; p < n; j <<= 1, m = p)
{
for(p = 0, i = n-j; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++)
if(sa[i] >= j) y[p++] = sa[i]-j;
for(i = 0; i < n; i++) wv[i] = x[y[i]];
for(i = 0; i < m; i++) ws1[i] = 0;
for(i = 0; i < n; i++) ws1[wv[i]]++;
for(i = 1; i < m; i++) ws1[i] += ws1[i-1];
for(i = n-1; i >= 0; i--) sa[--ws1[wv[i]]] = y[i];
for(swap(x, y), p = 1, x[sa[0]] = 0, i = 1; i < n; i++)
x[sa[i]] = cmp(y, sa[i-1], sa[i], j)?p-1:p++;
}
}
int rank[maxn], height[maxn];
void calheight(int *r, int *sa, int n)
{
int i, j, k = 0;
for(i = 1; i <= n; i++) rank[sa[i]] = i;
for(int i = 0; i < n; height[rank[i++]] = k)
for(k?k--:0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k++);
return ;
}
int dp[maxn][30];
void RMQ(int len)
{
for(int i = 1; i <= len; i++)
dp[i][0] = height[i];
for(int j = 1; 1<<j <= maxn; j++)
{
for(int i = 1; i+(1<<j)-1 <= len; i++)
dp[i][j] = min(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
}
}
int lg[maxn];
int querry(int l, int r)
{
int k = lg[r-l+1];
return min(dp[l][k], dp[r-(1<<k)+1][k]);
}
void init()
{
lg[0] = -1;
for (int i = 1; i < maxn; ++i)
lg[i] = lg[i>>1] + 1;
}
int seq[maxn];
void Del1(int n)
{
int Max = 0;
int pos = 0;
for(int i = 0; i < n; i++)
{
int l = rank[i];
int r = rank[2*n-i+1];
if(l > r) swap(l, r);
int tmp = querry(l+1, r);
if(tmp*2 > Max)
{
Max = tmp*2;
pos = i;
}
l = rank[i];
r = rank[2*n-i];
if(l > r) swap(l, r);
tmp = querry(l+1, r);
if(tmp*2-1 > Max)
{
Max = tmp*2-1;
pos = i;
}
}
for (int i = pos-Max/2; Max--; ++i)
putchar(seq[i]);
puts("");
return ;
}
void Del(int n)
{
int Max = 0;
for(int i = 1; i <= n/2; i++)
{
for(int j = 0; i*j+i < n; j++)
{
int l = rank[i*j];
int r = rank[i*j+i];
if(l > r) swap(l, r);
int x = querry(l+1, r);
int y = 0;
int xp = i - x%i;
if(xp && j)
{
l = rank[i*j-xp];
r = rank[i*j+i-xp];
if(l > r) swap(l, r);
y = querry(l+1, r);
}
Max = max(Max, max(x/i, y/i)+1);
}
}
cout<<Max<<endl;
}
char str[10];
int main()
{
init();
int T;
cin >>T;
while(T--)
{
int n;
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
scanf("%s", str);
seq[i] = str[0]-'a'+1;
}
seq[n] = 0;
da(seq, sa, n+1, 5);
calheight(seq, sa, n);
RMQ(n);
Del(n);
}
return 0;
}
相關文章
- POJ 3693 Maximum repetition substring(字尾陣列求最長重複子串)陣列
- POJ 1743 Musical Theme (字尾陣列,求最長不重疊重複子串)陣列
- POJ 3294 Life Forms(字尾陣列求k個串的最長子串)ORM陣列
- poj 2774 求兩字串的最長公共子串 字尾陣列字串陣列
- SPOJ 694 求一個字串有多少子串 字尾陣列字串陣列
- ural 1297 最長迴文子串 字尾陣列陣列
- SPOJ 220. Relevant Phrases of Annihilation(字尾陣列多次不重疊子串)陣列
- 求字串中不含重複字元的最長子串字串字元
- 無重複字元的最長子串字元
- POJ 2217-Secretary(字尾陣列+高度陣列-最大公共子串長度)陣列
- java無重複字元的最長子串Java字元
- 3 無重複字元的最長子串字元
- POJ 3415 Common Substrings(字尾陣列求重複字串)陣列字串
- 3. 無重複字元的最長子串字元
- poj3080-kmp+列舉子串 求最長公共子串KMP
- 字尾陣列複習陣列
- POJ 2774-Long Long Message(字尾陣列+高度陣列-最大公共子串長度)陣列
- 演算法練習:求字串的最長重複子串(Java實現)演算法字串Java
- HDU 4622 Reincarnation( 任意區間子串的長度, 字尾陣列+RMQ)陣列MQ
- LeetCode——無重複字元的最長子串LeetCode字元
- 演算法-無重複字元的最長子串演算法字元
- 最長公共子串 二維陣列 Go實現陣列Go
- URAL 1297. Palindrome(字尾陣列求最大回文串)陣列
- leetcode 之無重複字元的最長子串LeetCode字元
- 【LeetCode】3 無重複字元的最長子串LeetCode字元
- 【leetcode】【java】【3、無重複字元的最長子串】LeetCodeJava字元
- leetcode-3無重複字元的最長子串LeetCode字元
- LeetCode-3. 無重複字元的最長子串LeetCode字元
- Leetcode 3. 無重複字元的最長子串LeetCode字元
- POJ 3415-Common Substrings(字尾陣列+單調棧-公共子串的長度)陣列
- 最長子串
- LEECODE 5 求最長迴文子串
- 每日leetcode——3. 無重複字元的最長子串LeetCode字元
- LCR 016. 無重複字元的最長子串(中)字元
- 978 最長湍流子陣列陣列
- 【LeetCode動態規劃#14】子序列系列題(最長遞增子序列、最長連續遞增序列、最長重複子陣列、最長公共子序列)LeetCode動態規劃陣列
- SPOJ 694. Distinct Substrings,705. New Distinct Substrings(字尾陣列)陣列
- HDU 5769-Substring(字尾陣列-不相同的子串的個數)陣列