您的位置:首页 > 理论基础 > 计算机网络

hdu 5442 (ACM-ICPC2015长春网络赛F题)

2015-09-14 12:50 369 查看
题意:给出一个字符串,长度是2*10^4。将它首尾相接形成环,并在环上找一个起始点顺时针或逆时针走一圈,求字典序最大的走法,如果有多个答案则找起始点最小的,若起始点也相同则选择顺时针。

分析:后缀数组。

首先,需要补充后缀数组的基本知识的话,看这个链接。

/article/4912362.html

我利用这道题重新整理了后缀数组的模板如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define d(x)

const int MAX_N = (int)(4e4) + 100;

//call init_RMQ(f[], n) first.
//then call query(a, b) to quest the RMQ of [a, b].
int power[30];
int st[MAX_N * 2][32];
int ln[MAX_N * 2];

//returns the index of the first minimum value in [x, y]
void init_RMQ(int f[], int n)
{
int i, j;
for (power[0] = 1, i = 1; i < 21; i++)
{
power[i] = 2 * power[i - 1];
}
for (i = 0; i < n; i++)
{
st[i][0] = i;
}
ln[0] = -1;
for (int i = 1; i <= n; i++)
{
ln[i] = ln[i >> 1] + 1;
}
for (j = 1; j < ln
; j++)
{
for (i = 0; i < n; i++)
{
if (i + power[j - 1] - 1 >= n)
{
break;
}
//for maximum, change ">" to "<"
//for the last, change "<" or ">" to "<=" or ">="
if (f[st[i][j - 1]] > f[st[i + power[j - 1]][j - 1]])
{
st[i][j] = st[i + power[j - 1]][j - 1];
}
else
{
st[i][j] = st[i][j - 1];
}
}
}
}

int query(int f[], int x, int y)
{
if(x > y)
{
swap(x, y);
}
int k = ln[y - x + 1];
//for maximum, change ">" to "<"
//for the last, change "<" or ">" to "<=" or ">="
if (f[st[x][k]] > f[st[y - power[k] + 1][k]])
return st[y - power[k] + 1][k];
return st[x][k];
}

//first use the constructed function
//call function lcp(l, r) to get the longest common prefix of sa[l] and sa[r]
//have access to the member of sa, myrank, height and so on
//height is the LCP of sa[i] and sa[i + 1]
class SuffixArray
{
public:
char* s;
int n, sa[MAX_N], height[MAX_N], myrank[MAX_N];
int tmp[MAX_N], top[MAX_N];

SuffixArray()
{}

//the string and the length of the string
SuffixArray(char* st, int len)
{
s = st;
n = len + 1;
make_sa();
make_lcp();
}

void make_sa()
{
// O(N * log N)
int na = (n < 256 ? 256 : n);
memset(top, 0, na * sizeof(int));
for (int i = 0; i < n ; i++)
top[myrank[i] = s[i] & 0xff]++;
for (int i = 1; i < na; i++)
top[i] += top[i - 1];
for (int i = 0; i < n ; i++)
sa[--top[ myrank[i]]] = i;
int x;
for (int len = 1; len < n; len <<= 1)
{
for (int i = 0; i < n; i++)
{
x = sa[i] - len;
if (x < 0)
x += n;
tmp[top[myrank[x]]++] = x;
}
sa[tmp[top[0] = 0]] = x = 0;
for (int i = 1; i < n; i++)
{
if (myrank[tmp[i]] != myrank[tmp[i-1]] ||
myrank[tmp[i]+len]!=myrank[tmp[i-1]+len])
top[++x] = i;
sa[tmp[i]] = x;
}
memcpy(myrank, sa , n * sizeof(int));
memcpy(sa , tmp, n * sizeof(int));
if (x >= n - 1)
break;
}
}

void make_lcp()
{
// O(4 * N)
int i, j, k;
for (j = myrank[height[i = k = 0] = 0]; i < n - 1; i++, k++)
{
while (k >= 0 && s[i] != s[sa[j - 1] + k])
{
height[j - 1] = (k--);
j = myrank[sa[j] + 1];
}
}
init_RMQ(height, n - 1);
}

int lcp(int l, int r)
{
return height[query(height, l, r - 1)];
}
};

SuffixArray suffix;
int len;
char ans1[MAX_N], ans2[MAX_N];
int pos1, pos2;
char s[MAX_N];

int work1(char* ans)
{
int p = len * 2;
while (suffix.sa[p] >= len)
p--;
for (int i = p - 1; i >= 0; i--)
{
if (suffix.lcp(i, i + 1) <= len)
break;
if (suffix.sa[i] < suffix.sa[p])
{
p = i;
}
}
memcpy(ans, s + suffix.sa[p], len);
ans[len] = 0;
return suffix.sa[p];
}

int work2(char* ans)
{
int p = len * 2;
while (suffix.sa[p] >= len)
p--;
for (int i = p - 1; i >= 0; i--)
{
if (suffix.lcp(i, i + 1) <= len)
break;
if (suffix.sa[i] > suffix.sa[p])
{
p = i;
}
}
memcpy(ans, s + suffix.sa[p], len);
ans[len] = 0;
return suffix.sa[p];
}

int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d", &len);
scanf("%s", s);
for (int i = 0; i < len; i++)
{
s[len + i] = s[i];
}
suffix = SuffixArray(s, len * 2);
pos1 = work1(ans1);
reverse(s, s + len * 2);
suffix = SuffixArray(s, len * 2);
pos2 = work2(ans2);
pos2 = len - 1 - pos2;

if (strcmp(ans1, ans2) > 0)
{
printf("%d 0\n", pos1 + 1);
continue;
}else if (strcmp(ans1, ans2) < 0)
{
printf("%d 1\n", pos2 + 1);
continue;
}else if (pos1 <= pos2)
{
printf("%d 0\n", pos1 + 1);
continue;
}else
{
printf("%d 1\n", pos2 + 1);
}
}
return 0;
}


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