对应 ural 题目:点击打开链接
| Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %I64d & %I64u |
Description
Input
Output
Sample Input
| input | output |
|---|---|
ThesampletextthatcouldbereadedthesameinbothordersArozaupalanalapuazorA |
ArozaupalanalapuazorA |
Source
题意:求给出字符串的最长回文子串,如果有多个解,则输出最左边的解
思路:后缀数组基本应用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MS(x, y) memset(x, y, sizeof(x))
#define MIN(x, y) ((x)<(y)?(x):(y))
#define MAX(x, y) ((x)>(y)?(x):(y))
const int MAXN = 2000+10;
const int INF = 1<<30;
int dp[MAXN][20];
int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
int rank[MAXN],r[MAXN],sa[MAXN],height[MAXN];
char str[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, *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(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++) 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,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++;
}
return;
}
void calheight(int *r, int *sa, int n)
{
int i, j, k = 0;
for(i=1; i<n; i++) rank[sa[i]] = i;
for(i=0; i<n-1; height[rank[i++]] = k)
for(k ? k-- : 0,j=sa[rank[i]-1]; r[i+k] == r[j+k]; k++);
return;
}
void caldp(int n)
{
int i,j;
for(i=1; i<n; i++)
dp[i][0]=height[i];
for(j=1; j<=15; j++){ //注意这个要在外层
for(i=1; i<n; i++){
if(i+(1<<j)-1 < n){
dp[i][j]=MIN(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
}
}
}
}
int rmq(int l, int r)
{
int k = int(log(double(r-l+1))/log(2.0));
return MIN(dp[l][k], dp[r-(1<<k)+1][k]);
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%s", str))
{
MS(dp, 0);
MS(r, 0);
MS(sa, 0);
MS(rank, 0);
MS(height, 0);
MS(ws, 0);
MS(wv, 0);
MS(wa, 0);
MS(wb, 0);
int path = 0;
int i, n = 0;
int len = strlen(str);
for(i=0; i<len; i++)
r[n++] = (int)str[i] - (int)'A' + 1;
path = n;
r[n++] = 59;
for(i=len-1; i>=0; i--)
r[n++] = (int)str[i] - (int)'A' + 1;
r[n++] = 0;
da(r, sa, n, 60);
calheight(r, sa, n);
caldp(n);
int Set = -1, Len = 0;
int s = 0, l = 1, s1 = 0, l1 = 1, s2 = 0, l2 = 1;
int left, right, ok;
for(i=0; i<len; i++){
ok = 0;
if(i != len-1 && r[i] == r[i+1]){//回文串为偶数
ok = 1;
left = MIN(rank[i + 1], rank[n - 2 - i]);
right = MAX(rank[i + 1], rank[n - 2 - i]);
l1 = rmq(left + 1, right);
s1 = i - l1 + 1;
l1 = 2 * l1;
}
left = MIN(rank[i], rank[n - 2 - i]);
right = MAX(rank[i], rank[n - 2 - i]);
l2 = rmq(left + 1, right);
s2 = i - l2 + 1;
l2 = 2 * l2 - 1;
l = l2; s = s2;
if(ok) if(l1 > l2){
l = l1; s = s1;
}
if(l == Len && s < Set) Set = s;
else if(l > Len){
Len = l;
Set = s;
}
}
for(i=Set; i < Len+Set; i++)
printf("%c", r[i] + 'A' - 1);
printf("\n");
}
return 0;
}