ural 1297

来源:互联网 发布:排施工计划软件 编辑:程序博客网 时间:2024/06/18 11:12

      题意:求一个字符串的最长回文子串,有多个相同长度时输出最先出现的那个。

     对这道题,刚开始得到的一个提示是在原串后面加一个不可能出现的字符,再把原串反转拼接到后面,接着求由不可能出现字符分开的两部分的最长公共前缀。后来这样试了一下,很明显的就WA了,像abfeba这种数据会输出ab,很明显不行。于是看了题解,才明白。。。。

     正确的应该是枚举原串的每个字符,将其作为回文中心,当枚举到i时,分奇偶求两次,偶数求height[i+1]和height[len-i-1]的最长公共前缀,奇数时求height[i]和height[len-i-1]的最长公共前缀,取所有结果里最大的就行了。(len是拼接后字符串长度)

代码如下:

#include <cstdio>#include <stack>#include <set>#include <iostream>#include <string>#include <vector>#include <queue>#include <list>#include <functional>#include <cstring>#include <algorithm>#include <cctype>#include <string>#include <map>#include <iomanip>#include <cmath>#define LL long long#define ULL unsigned long long#define SZ(x) (int)x.size()#define MP(a, b) make_pair(a, b)#define MS(arr, num) memset(arr, num, sizeof(arr))#define PB push_back#define F first#define S second#define ROP freopen("input.txt", "r", stdin);#define MID(a, b) (a + ((b - a) >> 1))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define lrt rt << 1#define rrt rt << 1|1#define root 1,n,1#define BitCount(x) __builtin_popcount(x)#define BitCountll(x) __builtin_popcountll(x)#define LeftPos(x) 32 - __builtin_clz(x) - 1#define LeftPosll(x) 64 - __builtin_clzll(x) - 1const double PI = acos(-1.0);const int INF = 1e7;using namespace std;const double eps = 1e-5;const int MAXN = 300 + 10;const int MOD = 1000007;const double M=1e-8;const int N=2100;typedef pair<int, int> pii;typedef pair<int, string> pis;int m,sa[N],rank[N],height[N],dp[N][N];int wa[N],wb[N],wv[N], cnt[N];bool cmp(int *y,int a,int b,int l){    return y[a]==y[b] && y[a+l]==y[b+l];}void da(char s[],int n,int m){    int i,j,p,*x=wa,*y=wb;    MS(cnt,0);    for (i=0;i<n;i++) cnt[x[i]=s[i]]++;    for (i=1;i<m;i++) cnt[i]+=cnt[i-1];    for (i=n-1;i>=0;i--) sa[--cnt[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]];        MS(cnt,0);        for (i=0;i<n;i++) cnt[wv[i]]++;        for (i=1;i<m;i++) cnt[i]+=cnt[i-1];        for (i=n-1;i>=0;i--) sa[--cnt[wv[i]]]=y[i];        swap(x,y);        for (i=1,p=1,x[sa[0]]=0;i<n;i++) {            x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;        }    }}void getHeight(char s[],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];s[i+k]==s[j+k];k++) ;    }}void rmq(int n){    int i,j,k=log(n)/log(2);    for (i=1;i<=n;i++) dp[i][0]=height[i];    for (j=1;j<=k;j++)        for (i=1;i+(1<<j)-1<=n;i++) {            dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);    }}int query(int x,int y){    int k=log(y-x+1)/log(2);    return min(dp[x][k],dp[y-(1<<k)+1][k]);}int lcp(int x,int y){    int l=rank[x],r=rank[y];    if (l>r) swap(l,r);    l++;    return query(l,r);}char s[N],r[N];int n;void slove(){    int i,j,mx1=-INF,mx2=-INF,p1,p2,p;    for (i=0;i<n/2;i++) {     // 奇数时        int t=lcp(i,n-i-1);          if (t>mx1) mx1=t,p1=i;    }    for (i=0;i<n/2-1;i++) {   //  偶数时        int t=lcp(i+1,n-i-1);        if (t>mx2) mx2=t,p2=i;    }    int len;    if (mx2*2>mx1*2-1) {     // 求最大长度        len=mx2*2;        p1=p2,mx1=mx2;    }    else {        len=mx1*2-1;    }     //cout<<p1-mx1+1<<" "<<len<<endl;    len+=p1-mx1+1;    for (i=p1-mx1+1;i<len;i++) putchar(s[i]);  puts("");}int main(){    int i,j;    while(~scanf("%s",s))    {        n=strlen(s);        r[0]='\0';        strcat(r,s);        reverse(r,r+n);        s[n]='|',s[n+1]='\0';        strcat(s,r);        n=strlen(s);        s[n]=0;        da(s,n+1,128);        getHeight(s,n);        rmq(n);//        for (i=1;i<=n;i++) cout<<sa[i]<<" "; cout<<endl;//        for (i=0;i<n;i++) cout<<rank[i]<<" "; cout<<endl;//        for (i=1;i<=n;i++) cout<<height[i]<<" "; cout<<endl;        slove();    }}/*descramblerwillchoosethetextscanningdirectionatrandomabfeba*/


0 0
原创粉丝点击