Palindrome

Palindrome

时间限制: 1000ms   内存限制: 128M

    给出一个仅由小写字母构成的字符串,求其最长回文子串的长度。由于该字符串很长,故将其以压缩后的形式给出。压缩后的字符串有n段,其中第i段用一个整数lengthi和一个小写字母ci来描述,表示第i段是由lengthi个连续的小写字母ci组成。

输入第一行为一个整数T,表示一共有T组测试数据。

对于每组测试数据:

第一行为一个整数n1n100000)。

接下来n行中,第i行有一个整数lengthi和一个小写字母ci以一个空格间隔(1lengthi109ci为小写字母az中的一个)。

对于每组测试数据:输出一个整数表示最长回文子串长度。

 复制
1
5
1 a
1 a
3 b
2 a
4 c
7
分析:可以先把连续相同字符放在一起;
   然后就是求最长回文子串,枚举每一位字符,然后无脑二分哈希就好了;
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int n,m,k,t,b[maxn],cnt,mo=12345;
char op[maxn];
ll a[maxn],pre[maxn],len[maxn];
unsigned ll h1[maxn],h2[maxn],h3[maxn],h4[maxn],xp[maxn];
bool check(int len,int sta,int stb,unsigned ll *h1,unsigned ll *h2)
{
    return h1[sta]-h1[sta+len]*xp[len]==h2[stb]-h2[stb-len]*xp[len];
}
int main()
{
    int i,j;
    xp[0]=1;
    for(i=1;i<=maxn-10;i++)xp[i]=xp[i-1]*mo;
    scanf("%d",&t);
    while(t--)
    {
        cnt=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            int num=0;
            scanf("%d%s",&num,op);
            if(op[0]!=b[cnt])
            {
                b[++cnt]=op[0];
                a[cnt]=num;
                pre[cnt]=pre[cnt-1]+a[cnt];
            }
            else a[cnt]+=num,pre[cnt]+=num;
        }
        h1[cnt+1]=h2[cnt+1]=0;
        for(i=cnt;i>=1;i--)
        {
            h1[i]=h1[i+1]*mo+a[i];
            h2[i]=h2[i+1]*mo+b[i]-'a';
        }
        h3[0]=h4[0]=0;
        for(i=1;i<=cnt;i++)
        {
            h3[i]=h3[i-1]*mo+a[i];
            h4[i]=h4[i-1]*mo+b[i]-'a';
        }
        ll ret=0;
        for(i=1;i<=cnt;i++)
        {
            int l=1,r=min(i,cnt-i+1),ma;
            while(l<=r)
            {
                int mid=l+r>>1;
                if(check(mid,i-mid+1,i+mid-1,h1,h3)&&check(mid,i-mid+1,i+mid-1,h2,h4))
                {
                    ma=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }
            ll now=pre[i+ma-1]-pre[i-ma];
            if(b[i+ma]==b[i-ma]&&i-ma>=1&&i+ma<=cnt)now+=2*min(a[i-ma],a[i+ma]);
            ret=max(ret,now);
        }
        printf("%lld\n",ret);
    }
    return 0;
}
posted @ 2017-05-17 17:01  mxzf0213  阅读(395)  评论(0编辑  收藏  举报