对应 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; }