您的位置:首页 > 其它

Milk Patterns - poj 3261 (求重复k次的最长子串)

2015-09-04 14:39 381 查看
题目大意:给你一个数组,求这个数组里面至少重复k次的子串。

分析:后缀数组的练手题目...不过给的数字比较大,可以先离散化处理一下即可。

代码如下:
===============================================================================================================================

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 2e4+7;

struct SuffixArr
{
int tempx[MAXN], tempy[MAXN], text[MAXN], Hash[MAXN];
int rank[MAXN], sa[MAXN], sum[MAXN], height[MAXN];
int *x, *y, N, MaxId;

void GetText(int data[], int len)
{
N = len, x=tempx, y=tempy;

for(int i=0; i<N; i++)
Hash[i] = data[i];

sort(Hash, Hash+N);
MaxId = unique(Hash, Hash+N) - Hash;

for(int i=0; i<N; i++)
{
text[i] = x[i] = lower_bound(Hash, Hash+MaxId, data[i])-Hash;
y[i] = i;
}
}
bool cmp(int i, int len)
{
if(sa[i]+len > N || sa[i-1]+len > N)
return false;
if(y[sa[i]]!=y[sa[i-1]] || y[sa[i]+len]!=y[sa[i-1]+len])
return false;

return true;
}
void BaseSort()
{
for(int i=0; i<MaxId; i++)
sum[i] = 0;
for(int i=0; i<N; i++)
sum[ x[ y[i] ] ] += 1;
for(int i=1; i<MaxId; i++)
sum[i] += sum[i-1];
for(int i=N-1; i>=0; i--)
sa[ --sum[ x[ y[i] ] ] ] = y[i];
}
void GetSa()
{
BaseSort();

for(int len=1; len <= N; len<<=1)
{
int id = 0;

for(int i=N-len; i<N; i++)
y[id++] = i;
for(int i=0; i<N; i++)if(sa[i] >= len)
y[id++] = sa[i] - len;

BaseSort();
swap(x, y);
x[ sa[0] ] = id = 0;

for(int i=1; i<N; i++)
{
if(cmp(i, len) == true)
x[sa[i]] = id;
else
x[sa[i]] = ++id;
}

MaxId = id+1;

if(MaxId >= N)
break;
}
}
void GetHeight()
{
for(int i=0; i<N; i++)
rank[sa[i]] = i;

///  debug(text);
///  debug(rank);

for(int k=0, i=0; i<N; i++)
{
if(!rank[i])
{
height[0] = k = 0;
continue;
}
if(k)k--;

int pre = sa[ rank[i]-1 ];

while(text[i+k] == text[pre+k])
k++;
height[rank[i]] = k;
}

///debug(height);
}
void debug(int p[])
{
for(int i=0; i<N; i++)
printf("%d ", p[i]);
printf("\n");
}
};

SuffixArr suf;
int data[MAXN];

bool Find(int times, int k)
{
int cnt=0;

for(int i=0; i<suf.N; i++)
{
if(suf.height[i] < k)
cnt = 0;
else
{
cnt += 1;
if(cnt == times-1)
return true;
}
}

return false;
}

int main()
{
int N, times;

while(scanf("%d%d", &N, ×) != EOF)
{
for(int i=0; i<N; i++)
scanf("%d", &data[i]);
data
= -1;

suf.GetText(data, N+1);
suf.GetSa();
suf.GetHeight();

int L=0, R=N, ans=0;

while(L <= R)
{
int Mid = (L+R)>>1;

if(Find(times, Mid) == true)
{
ans = Mid;
L = Mid + 1;
}
else
R = Mid - 1;
}

printf("%d\n", ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: