Palindrome - URAL - 1297(求回文串)

题目大意:RT
 
分析:后缀数组求回文串,不得不说确实比较麻烦,尤其是再用线段数进行查询,需要注意的细节地方比较多,比赛实用性不高......不过练练手还是可以的。
 
线段数+后缀数组代码如下:
===========================================================================================================================================
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 1e4+7;

struct SuffixArr
{
    int tempx[MAXN], tempy[MAXN], text[MAXN];
    int rank[MAXN], sa[MAXN], height[MAXN], sum[MAXN];
    int *x, *y, N, MaxId;

    void GetText(char s[])
    {
        N = strlen(s)*2+2, MaxId = 200;
        x = tempx, y = tempy;
        int i;
        for(i=0; s[i]; i++)
        {
            text[i] = text[N-i-2] = x[i] = x[N-i-2] = (int)s[i];
            y[i] = i, y[N-i-2] = N-i-2;
        }

        text[i] = x[i] = 1, y[i] = i;
        text[N-1] = x[N-1] = 0, y[N-1] = N-1;

       /// debug();
    }
    bool cmp(int i, int len)
    {
        if(sa[i]+len > N || sa[i-1]+len > N)
            return false;
        if(y[sa[i]] != y[sa[i-1]] || y[sa[i]+len] != y[sa[i-1]+len])
            return false;

        return true;
    }
    void baseSort()
    {
        for(int i=0; i<MaxId; i++)
            sum[i] = 0;
        for(int i=0; i<N; i++)
            sum[ x[ y[i] ] ] += 1;
        for(int i=1; i<MaxId; i++)
            sum[i] += sum[i-1];
        for(int i=N-1; i>=0; i--)
            sa[ --sum[ x[ y[i] ] ] ] = y[i];
    }
    void GetSa()
    {
        baseSort();

        for(int len=1; len<=N; len<<=1)
        {
            int id = 0;

            for(int i=N-len; i<N; i++)
                y[id++] = i;
            for(int i=0; i<N; i++)if(sa[i] >= len)
                y[id++] = sa[i] - len;

            baseSort();
            swap(x, y);
            x[ sa[0] ] = id = 0;

            for(int i=1; i<N; i++)
            {
                if(cmp(i, len) == true)
                    x[ sa[i] ] = id;
                else
                    x[ sa[i] ] = ++id;
            }

            MaxId = id + 1;

            if(MaxId >= N)break;
        }
    }
    void GetHeight()
    {
        for(int i=0; i<N; i++)
            rank[ sa[i] ] = i;


        for(int k=0, i=0; i<N; i++)
        {
            if(!rank[i])
            {
                height[0] = k = 0;
                continue;
            }
            if(k)k--;

            int pre = sa[ rank[i]-1 ];

            while(text[i+k] == text[pre+k])
                k++;
            height[rank[i]] = k;
        }
       /// debug();
    }

    void debug()
    {
        for(int i=0; i<N; i++)
            printf("%d: %d\n", i, height[i]);
    }
};
struct segmentTree
{
    int val[MAXN], L[MAXN], R[MAXN];

    void Build(int root, int l, int r, int p[])
    {
        L[root] = l, R[root] = r;

        if(l == r)
        {
            val[root] = p[l];
            return ;
        }

        int Mid = (l+r)>>1;

        Build(root<<1, l, Mid, p);
        Build(root<<1|1, Mid+1, r, p);

        val[root] = min(val[root<<1], val[root<<1|1]);
    }
    int  Query(int root, int u, int v)
    {

        if(L[root] == u && R[root] == v)
            return val[root];

        int Mid = (L[root]+R[root]) / 2;

        if(v <= Mid)
            return Query(root<<1, u, v);
        else if(u > Mid)
            return Query(root<<1|1, u, v);
        else
            return min(Query(root<<1, u, Mid), Query(root<<1|1, Mid+1, v));
    }
};

SuffixArr suf;
segmentTree seg;
char s[MAXN];

int main()
{
    while(scanf("%s", s) != EOF)
    {
        int len = strlen(s)+1;

        suf.GetText(s);
        suf.GetSa();
        suf.GetHeight();

        seg.Build(1, 0, suf.N-1, suf.height);

        int MaxLen=1, k=0, x, y;

        for(int i=0; i<len-1; i++)
        for(int j=0; j<2; j++)
        {
            if(j==0)
                x = suf.rank[len*2-i-2];
            else
                x = suf.rank[len*2-i-1];

            if(i==0 && j)continue;

            y = suf.rank[i+1];

            if(x > y)swap(x, y);

            int m = seg.Query(1, x+1, y) * 2 + j;

            if(MaxLen < m)
            {
                MaxLen = m;
                k = i-(m+j)/2+1;
            }
        }

        s[k+MaxLen] = 0;

        printf("%s\n", s+k);
    }

    return 0;
}
View Code

 

posted @ 2015-09-05 10:37  无忧望月  阅读(130)  评论(0编辑  收藏  举报
levels of contents