BZOJ 2160: 拉拉队排练(回文树)
传送门:
[1]:BZOJ
[2]:洛谷
•题意
求串 s 中出现的所有奇回文串,并按照长度由大到小排序;
输出前 k 个奇回文串的乘积 mod 19930726;
如果奇回文串的个数不足 k 个,输出 -1;
•题解
将串 s 跑一边回文自动机;
将求解出的 len,cnt 数组存入一个结构体中并按照 len 由大到小排序;
将前 k 个奇回文串的长度相乘就行;
记得用快速幂,并且只要奇回文串的长度乘积;
•Code
View Code1 #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\n",ans); 134 }