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;
}

浙公网安备 33010602011771号