题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文。
思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能出现的字符隔开。然后就用到后缀数组的性质了,
我们枚举每一个原始字符串中的字符以它为中心(分为奇数和偶数两种情况)进行查找,比如对于下标为i的字符,当回文串为奇数时,我们要求的就是i的后缀与2*n-i的
后缀的最长公共前缀了,然后根据height数组的性质就转化成求height[i+1]...height[2*n-i]中的最小值了,这时我们想到了用RMQ求区间最值了,对于不会RMQ的童
鞋可以先去学习下,再来做这道题,具体看代码实现:
代码实现:
#include#include #include #include using namespace std;#define N 2010int ws1[N],wv[N],wa[N],wb[N];int rank1[N],height[N],sa[N];char str[N];int a[N],n;int dp[N][25];int min(int a,int b){ return a>b?b:a;}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 =0;i--) sa[--ws1[x[i]]]=i; for(j=1,p=1;p =j) y[p++]=sa[i]-j; for(i=0;i =0;i--) sa[--ws1[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i b) swap(a,b); a++; int t=(int)(log(double(b-a+1))/log(2.00)); return min(dp[a][t],dp[b-(1< 0)//偶数时 { res=lcp(i,2*n-i+1)*2; if(max