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