zoukankan      html  css  js  c++  java
  • bzoj2160拉拉队排练

    bzoj2160拉拉队排练

    题意:

    给一个字符串,求最长的k个回文子串(此处回文子串长度必须为奇数)长度的乘积。字符串长度≤1000000

    题解:

    先用manacher预处理出第i个字符为中心的最长回文子串一端长度p[i],然后cnt[1]++,cnt[2*p[i]+1]--,最后cnt[i]+=cnt[i-2]求出所有长度的回文子串个数。然后用快速幂求出相同长度的回文子串的长度乘积即可。注意k要开long long!

    反思:manacher是一种用来O(n)求每个字符为中心的最长回文子串一端长度的算法(如果要求的回文子串长度可以是偶数,就在原串两端和每两个字符之间插入一个特殊字符,最后答案/2即可)。主要思想是当前求的p[i]和它的某个对称点j是等价的,可以借助p[j]来求。具体看这个

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 1000010
     6 #define mod 19930726
     7 #define ll long long
     8 using namespace std;
     9 
    10 int n,mx,id,p[maxn],cnt[maxn]; char s[maxn]; ll ans,k;
    11 ll power(ll a,int b){
    12     if(b==0)return 1; if(b==1)return a;
    13     ll c=power(a,b>>1);
    14     if(b&1)return c*c%mod*a%mod;else return c*c%mod;
    15 }
    16 int main(){
    17     scanf("%d%lld",&n,&k); scanf("%s",s+1); mx=0; id=0;
    18     inc(i,1,n){
    19         if(mx>i)p[i]=min(p[2*id-i],mx-i);else p[i]=1;
    20         while(i-p[i]>=1&&i+p[i]<=n&&s[i-p[i]]==s[i+p[i]])p[i]++; cnt[1]++; cnt[2*p[i]+1]--;
    21         if(mx<i+p[i]-1)mx=i+p[i]-1,id=i;
    22     }
    23     inc(i,3,n)if(i&1)cnt[i]+=cnt[i-2]; ans=1;
    24     for(int i=n;i>=1;i--){
    25         if(cnt[i]){
    26             if(k>=cnt[i]){ans=(ans*power(i,cnt[i]))%mod; k-=cnt[i];}else{ans=(ans*power(i,k))%mod; k=0;}
    27             if(!k)break;
    28         }
    29     }
    30     if(k)printf("-1");else printf("%lld",ans); return 0;
    31 }

    20160817

  • 相关阅读:
    三级联动下拉菜单1
    IP地址查询接口及调用方法
    实现简单的网页拖拽效果
    [转载]PHP如何获取客户端真实IP
    mysql(二)连接查询
    php exec 执行php脚本
    PHP-将某一目录下文件压缩成zip格式
    从读书时代想我的程序之路
    Github上建立自己的网站
    小米手机购买程序,如果是我,我会怎么写
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5782042.html
Copyright © 2011-2022 走看看