• BZOJ 2160: 拉拉队排练(回文树)


    传送门:

      [1]:BZOJ

      [2]:洛谷

    •题意

      求串 s 中出现的所有奇回文串,并按照长度由大到小排序;

      输出前 k 个奇回文串的乘积 mod 19930726;

      如果奇回文串的个数不足 k 个,输出 -1;

    •题解

      将串 s 跑一边回文自动机;

      将求解出的 len,cnt 数组存入一个结构体中并按照 len 由大到小排序;

      将前 k 个奇回文串的长度相乘就行;

      记得用快速幂,并且只要奇回文串的长度乘积;

    •Code

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 const int MOD=19930726;
      5 const int maxn=1e6+50;
      6  
      7 int n;
      8 ll k;
      9 char s[maxn];
     10  
     11 struct PAM
     12 {
     13     int tot;
     14     int last;
     15     ll cnt[maxn];
     16     ll len[maxn];
     17     int fail[maxn];
     18     int son[maxn][30];
     19  
     20     int newNode(int Len)
     21     {
     22         for(int i=0;i < 30;++i)
     23             son[tot][i]=0;
     24  
     25         len[tot]=Len;
     26         fail[tot]=0;
     27         cnt[tot]=0;
     28  
     29         return tot++;
     30     }
     31     int getFail(int p,int i)
     32     {
     33         while(s[i-len[p]-1] != s[i])
     34             p=fail[p];
     35         return p;
     36     }
     37     void Init()
     38     {
     39         tot=0;
     40         last=0;
     41  
     42         newNode(0);
     43         newNode(-1);
     44  
     45         fail[0]=1;
     46     }
     47     void Count()
     48     {
     49         for(int i=tot-1;i >= 0;--i)
     50             cnt[fail[i]] += cnt[i];
     51     }
     52     void pam()
     53     {
     54         Init();
     55  
     56         for(int i=1;i <= n;++i)
     57         {
     58             s[i]=s[i]-'a'+1;
     59  
     60             int cur=getFail(last,i);
     61  
     62             if(!son[cur][s[i]])
     63             {
     64                 int now=newNode(len[cur]+2);
     65                 fail[now]=son[getFail(fail[cur],i)][s[i]];
     66                 son[cur][s[i]]=now;
     67  
     68             }
     69             cnt[last=son[cur][s[i]]]++;
     70         }
     71         Count();
     72     }
     73 }_pam;
     74 struct Data
     75 {
     76     ll cnt;
     77     ll len;
     78     bool operator < (const Data &obj) const
     79     {
     80         return len > obj.len;
     81     }
     82 }a[maxn];
     83  
     84 ll qPow(ll a,ll b,ll m)
     85 {
     86     ll ans=1;
     87     a %= m;
     88     while(b)
     89     {
     90         if(b&1)
     91             ans=ans*a%m;
     92         a=a*a%m;
     93         b >>= 1;
     94     }
     95     return ans;
     96 }
     97 int main()
     98 {
     99     scanf("%d%lld",&n,&k);
    100     scanf("%s",s+1);
    101     s[0]='#';
    102  
    103     _pam.pam();
    104  
    105     int x=0;
    106     for(int i=2;i < _pam.tot;i++)
    107         a[++x]=Data{_pam.cnt[i],_pam.len[i]};
    108  
    109     sort(a+1,a+x+1);
    110  
    111     int index=1;
    112     ll ans=1;
    113     while(index <= x)
    114     {
    115         if(!(a[index].len&1))///坑:如果不是奇回文串,continue
    116         {
    117             index++;
    118             continue;
    119         }
    120  
    121         ll cur=min(k,a[index].cnt);
    122  
    123         ans *= qPow(a[index++].len,cur,MOD);
    124         ans %= MOD;
    125         k -= cur;
    126  
    127         if(k == 0)
    128             break;
    129     }
    130     if(k > 0)
    131         ans=-1;
    132  
    133     printf("%lld
    ",ans);
    134 }
    View Code
  • 相关阅读:
    myeclipse安装
    win下Velocity安装和试用
    win下Java环境安装
    零基础编程指南(By Turtle)
    快速将某个文件夹下的所有文件中的匹配数据替换
    补丁数组(增删改查都较快的数组)
    addView的误区
    NOIP普及组:买铅笔
    由抽奖软件想到的随机算法总结
    Codeforces Round #220 (Div. 2) 解题报告
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/11275316.html
Copyright © 2020-2023  润新知