zoukankan      html  css  js  c++  java
  • 2015 UESTC 搜索专题M题 Palindromic String 马拉车算法

     Palindromic String

    Time Limit: 20 Sec  Memory Limit: 256 MB

    题目连接

    http://acm.uestc.edu.cn/#/contest/show/61

    Description



    秋实大哥喜欢探索新鲜事物,最近他发明了一种新型回文串,叫K重回文串!今天他想用它来考考小朋友们。

    秋实大哥给出了与K重回文串有关的信息

        任何字符串都属于0重回文串,包括空字符串。
        一个长度为N的字符串S,S是K(k≥1)重回文串,当且仅当S是回文串,且其长度为⌊N2⌋的前缀和长度为⌊N2⌋的后缀是K−1重回文串。
        如果一个字符串是K重回文串,则称该字符串有一个回文值为K。一个字符串可以有多个回文值,比如S=abaaba,其回文值可为0,1,2,3。
        字符串的最大回文值是该字符串所有回文值的最大值。
        若字符串S的最大回文值≥1,则S一定是回文串。
        一个字符串S,如果其正着读和反着读是一样的,则称S是回文串,比如aabaa,aba,a。但abc,abab,aacba就不是回文串。
        一个长度为N的字符串S,其有N+1个前缀和N+1个后缀(不一定非空),比如abcde,有6个前缀,分别是空字符串,a,ab,abc,abcd,abcde;有6个后缀,分别是空字符串,e,de,cde,bcde,abcde。

    秋实大哥给你一个字符串S,他想问问你,S所有前缀的最大回文A的某一段完全重合,或者能够经过上下左右平移与折线A的某一段完全重合,则表示秋实大哥吹出了妹子的一部分旋律。

    Input

    第一行输入一个字符串S(0<|S|≤2⋅106),S包含 大写英文字母(A-Z),小写英文字母(a-z),数字(0-9)

    Output

    输出一个整数,表示S所有前缀的最大回文值之和。

    Sample Input

    CCeCeCCCee

    Sample Output

    4

    HINT

    题意

    题解:

    首先跑一发马拉车算法,然后得到所有字符的P数组,表示回文串的长度
    然后我们再递归求解
    然后就可以知道每一个回文串是几重
    (虽然我觉得复杂度可能会很高,但是跑的很快,不知道为什么……

    代码:

    //qscqesze
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define maxn 2000010
    #define mod 10007
    #define eps 1e-9
    int Num;
    char CH[20];
    //const int inf=0x7fffffff;   //нчоч╢С
    const int inf=0x3f3f3f3f;
    /*
    
    inline void P(int x)
    {
        Num=0;if(!x){putchar('0');puts("");return;}
        while(x>0)CH[++Num]=x%10,x/=10;
        while(Num)putchar(CH[Num--]+48);
        puts("");
    }
    */
    inline ll read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void P(int x)
    {
        Num=0;if(!x){putchar('0');puts("");return;}
        while(x>0)CH[++Num]=x%10,x/=10;
        while(Num)putchar(CH[Num--]+48);
        puts("");
    }
    //**************************************************************************************
    
    char s[maxn];
    char str[maxn*2];
    int l;
    int p[maxn*2];
    int manacher(char s[],int l)
    {
       int i,j,k,ans=0;
       for(i=1;i<=l;++i)str[i<<1]=s[i],str[(i<<1)+1]='#';
       str[1]='#';str[l*2+1]='#';str[0]='&';str[l*2+2]='$';
       l=l*2+1;j=0;
       for(i=1;i<=l;)
       {
           while(str[i-j-1]==str[i+j+1])++j;
           p[i]=j;if(j>ans)ans=j;
           for(k=1;k<=j&&p[i]-k!=p[i-k];++k)p[i+k]=min(p[i-k],p[i]-k);
           i+=k;j=max(j-k,0);
       }
       return ans;
    }
    
    int main()
    {
        scanf("%s",s+1);
        l=strlen(s+1);
        manacher(s,l);
        l=l*2+1;
        int ans=0;
        for(int i=2;i<=(l+1)/2;i++)
        {
            int tmp=p[i];
            int pos=i;
            while(tmp+1>=pos&&tmp!=0)
            {
                ans++;
                pos=(pos+1)/2;
                tmp=p[pos];
            }
            //cout<<ans<<endl;
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    【阿里云产品评测】装甲兵在云路上!
    区间交集问题
    信封嵌套问题
    twoSum问题的核心思想
    队列实现栈|栈实现队列
    设计Twitter 时间线
    如何使用单调栈解题
    二叉堆详解实现优先级队列
    git/SQL/正则表达式的在线练习网站
    我的 Redis 被入侵了
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4489812.html
Copyright © 2011-2022 走看看