zoukankan      html  css  js  c++  java
  • 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
    ",ret);
        }
        return 0;
    }
  • 相关阅读:
    设计模式之单例模式
    EditText的光标在4.0中的bug
    省赛热身赛之Median
    VB6获取本机所有IP地址公用函数
    省赛热身赛之Kagome Kagome
    OpenCV学习笔记(30)KAZE 算法原理与源码分析(四)KAZE特征的性能分析与比较
    使用jQuery validate 验证注册表单
    Oracle 发布 GlassFish 路线图
    Oracle 发布 GlassFish 路线图
    Java 中的双重检查(DoubleCheck)
  • 原文地址:https://www.cnblogs.com/dyzll/p/6868428.html
Copyright © 2011-2022 走看看