• P1659 [国家集训队]拉拉队排练


    P1659 [国家集训队]拉拉队排练

    题目大意

    n个字符组成的字符串,求最长的k个奇回文串乘积 n<=10^6

    回文自动机暴力统计,特判一下奇偶,快速幂乱搞就行了

    My complete code: 

    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const LL maxn=1000005;
    const LL MOD=19930726;
    struct node{
        int son[26],fail,len;
        LL val;
    }tree[maxn];
    LL len,last,nod,k,now,ans;
    LL tong[maxn],sot[maxn];
    char s[maxn];
    bool visit[maxn];
    inline void solve(){
        s[0]='#';
        tree[0].fail=1; tree[0].len=0;
        tree[1].fail=0; tree[1].len=-1;
        last=0;
        nod=1;
        
        for(LL i=1;i<=len;++i){
            while(s[i-tree[last].len-1]!=s[i])
                last=tree[last].fail;
            if(!tree[last].son[s[i]]){
                tree[++nod].len=tree[last].len+2;
                LL j=tree[last].fail;
                while(s[i-tree[j].len-1]!=s[i])
                    j=tree[j].fail;
                tree[nod].fail=tree[j].son[s[i]];
                tree[last].son[s[i]]=nod;
            }
            last=tree[last].son[s[i]];
            ++tree[last].val;
        }
    }
    inline LL pow(LL a,LL b){
        LL base=a,sum=1;;
        while(b){
            if(b&1)
                sum=sum*base%MOD;
            base=base*base%MOD;
            b>>=1;
        }
        return sum;
    }
    inline bool cmp(LL g1,LL g2){
        return g1>g2;
    }
    int main(){
        scanf("%lld%lld",&len,&k);
        scanf(" %s",s+1);
        for(LL i=1;i<=len;++i)
            s[i]-='a';
        solve();
        LL cnt=0;
        for(LL i=nod;i>=2;--i){
            tree[tree[i].fail].val+=tree[i].val;
            tong[tree[i].len]+=tree[i].val;
            if(tree[i].len&1&&!visit[tree[i].len]){
                sot[++cnt]=tree[i].len;
                visit[tree[i].len]=true;
            }
        }
        sort(sot+1,sot+1+cnt,cmp);
        ans=1;
        for(LL i=1;i<=cnt;++i)
            if(tong[sot[i]]){
        	    if(tong[sot[i]]>=k){
        		    ans=(ans*pow(sot[i],k))%MOD;
                    printf("%lld",ans);
                    return 0;
                }else{
                    ans=(ans*pow(sot[i],tong[sot[i]]))%MOD;
                    k-=tong[sot[i]];
                }
            }
        printf("-1"); 
        return 0;
    }
    

      

  • 相关阅读:
    stl_hash_set.h
    stl_hash_map.h
    stl_algobase.h
    stl_relops.h
    stl_algo.h
    VC6常用插件
    visual assist(VA)设置快捷键(其它安装的插件设置快捷键也在这里)
    SVN常用命令说明
    Android 调用相册 拍照 实现系统控件缩放 切割图片
    Android 一个3D相册源码
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10102309.html
Copyright © 2020-2023  润新知