首先求出 c n t [ i ] cnt[i] cnt[i]表示 P A M PAM PAM节点 i i i代表的回文串出现了几次
那么显然, i i i出现了 c n t [ i ] cnt[i] cnt[i]次,自然 f a i l [ i ] , f a i l [ f a i l [ i ] ] . . . . fail[i],fail[fail[i]].... fail[i],fail[fail[i]]....也至少出现了 c n t [ i ] cnt[i] cnt[i]次
所以倒序累加 c n t cnt cnt值,把自己的值加给 f a i l fail fail指针指向的节点就是答案
求出了 c n t cnt cnt值,直接贪心放即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
const int mod = 19930726;
int n; ll k;
char a[maxn];
int quick(int x,int n)
{
int ans = 1;
for( ; n ; n>>=1,x=1ll*x*x%mod )
if( n&1 ) ans = 1ll*ans*x%mod;
return ans;
}
struct PAM
{
int len[maxn],fail[maxn],zi[maxn][26],id,las,cnt[maxn],c[maxn];
PAM()
{
id = las = 1;
fail[0] = 1,fail[1] = 1,len[0] = 0,len[1] = -1;
}
int get_fail(int u,int index)
{
while( a[index]!=a[index-len[u]-1] ) u = fail[u];
return u;
}
void insert(int c,int index)
{
int u = get_fail(las,index);
if( !zi[u][c] )
{
int now = ++id, v = get_fail( fail[u],index );
fail[now] = zi[v][c], len[now] = len[u]+2;
zi[u][c] = now;
}
las = zi[u][c]; cnt[las]++;
}
void build()
{
int n = strlen( a+1 );
for(int i=1;i<=n;i++) insert( a[i]-'a',i );
int ans = 1;
for(int i=id;i>=2;i--) cnt[fail[i]] += cnt[i];
for(int i=2;i<=id;i++) c[len[i]] += cnt[i];
for(int i=n;i>=1;i--)
{
if( i%2==0 ) continue;
if( c[i]>=k ) { ans = 1ll*ans*quick( i,k)%mod; k=0; break; }
else ans = 1ll*ans*quick(i,c[i] )%mod, k-=c[i];
}
if( k ) ans = -1;
cout << ans;
}
}pam;
signed main()
{
cin >> n >> k >> ( a+1 );
pam.build();
}