In addition, it is reasonable to assume that the agent will be sending a very long message, so John has simply to find the longest message satisfying the mentioned property.
Input
Output
Sample Input
input |
---|
ThesampletextthatcouldbereadedthesameinbothordersArozaupalanalapuazorA |
output |
ArozaupalanalapuazorA |
后缀数组,把原串反向后加入到后面
#include<stdio.h>
#include<string.h>
#define MAXD 2010
#define INF 0x3f3f3f3f
char b[MAXD];
int tree[4 * MAXD];
int N, M, P, r[MAXD], rank[MAXD], height[MAXD], sa[MAXD], wa[MAXD], wb[MAXD], ws[MAXD], wv[MAXD];
void init()
{
int i, j, k;
for(i = 0; b[i]; i ++)
r[i] = b[i];
r[N = i] = '$';
for(j = i - 1, ++ i; j >= 0; i ++, j --)
r[i] = b[j];
r[M = i] = 0;
}
int cmp(int *p, int x, int y, int l)
{
return p[x] == p[y] && p[x + l] == p[y + l];
}
void da(int n, int m)
{
int i, j, p, *x = wa, *y = wb, *t;
for(i = 0; i < m; i ++)
ws[i] = 0;
for(i = 0; i < n; i ++)
++ ws[x[i] = r[i]];
for(i = 1; i < m; i ++)
ws[i] += ws[i - 1];
for(i = n - 1; i >= 0; i --)
sa[-- ws[x[i]]] = i;
for(p = 1, j = 1; p < n; j *= 2, 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 ++)
ws[i] = 0;
for(i = 0; i < n; i ++)
++ ws[wv[i]];
for(i = 1; i < m; i ++)
ws[i] += ws[i - 1];
for(i = n - 1; i >= 0; i --)
sa[-- ws[wv[i]]] = y[i];
for(t = x, x = y, y = t, x[sa[0]] = 0, p = 1, i = 1; i < n; i ++)
x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1: p ++;
}
}
void calheight(int n)
{
int i, j, k = 0;
for(i = 1; i <= n; i ++)
rank[sa[i]] = i;
for(i = 0; i < n; height[rank[i ++]] = k)
for(k ? -- k : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k ++);
}
void build()
{
int i, j, k;
memset(tree, 0x3f, sizeof(tree));
for(P = 1; P < M + 2; P <<= 1);
for(i = 1; i <= M; i ++)
tree[P + i] = height[i];
for(i = P - 1; i > 0; i --)
tree[i] = tree[2 * i] < tree[2 * i + 1] ? tree[2 * i] : tree[2 * i + 1];
}
int search(int x, int y)
{
int i, j, t, min = INF;
if(x > y)
t = x, x = y, y = t;
for(i = P + x, j = P + y + 1; i ^ j ^ 1; i >>= 1, j >>= 1)
{
if((~i & 1) && tree[i ^ 1] < min)
min = tree[i ^ 1];
if((j & 1) && tree[j ^ 1] < min)
min = tree[j ^ 1];
}
return min;
}
void solve()
{
int i, j, k, ans, minr;
da(M + 1, 128);
calheight(M);
build();
ans = 0, minr = INF;
for(i = 0; i < N; i ++)
{
k = search(rank[i], rank[M - i - 1]);
if(2 * k - 1 > ans || (2 * k - 1 == ans && i - k + 1 < minr))
ans = 2 * k - 1, minr = i - k + 1;
k = search(rank[i], rank[M - i]);
if(2 * k > ans || (2 * k == ans && i - k < minr))
ans = 2 * k, minr = i - k;
}
for(i = 0; i < ans; i ++)
printf("%c", r[i + minr]);
printf("\n");
}
int main()
{
while(scanf("%s", b) == 1)
{
init();
solve();
}
return 0;
}