题目大意
给定一个长度为n的字符串,求他有多少个本质不同的回文子串,并输出第k小的。
n<=10^5
分析
看到字符串果断被吓到然后跳过了,后来大佬一说发现这题还是很可做的,我们可以先用manacher求出本质不同的所有字符串,再通过二分的方法就可以log^2的对所有字符串进行排序了。
代码
#include <bits/stdc++.h>
typedef std::pair<long long, long long> lp;
typedef std::pair<int, int> p;
typedef long long ll;
const long long MOD1 = 1e9 + 7;
const long long MOD2 = 55566677;
const long long POW1 = 2333333;
const long long POW2 = 23333;
const int N = 200005;
ll hash1[N], hash2[N];
ll pow1[N], pow2[N];
lp getHash(int x,int y)
{
ll h1 = (hash1[y] - 1ll * hash1[x - 1] * pow1[y - x + 1] % MOD1 + MOD1) % MOD1;
ll h2 = (hash2[y] - 1ll * hash2[x - 1] * pow2[y - x + 1] % MOD2 + MOD2) % MOD2;
return lp(h1, h2);
}
char a[N * 2];
int rad[N];
int n,k;
ll m;
char str[N];
std::map<lp, int> map;
std::vector<p> V;
void manacher()
{
for (int i = 0; i < n; i++)
{
a[i * 2] = '#';
a[i * 2 + 1] = str[i];
}
a[n * 2] = '#';
int len = n * 2 + 1, pos = 0, mx = 0;
int ans = 0;
for (int i = 0; i < len; i++)
{
if (i < mx)
rad[i] = std::min(rad[pos * 2 - i], mx - i);
else rad[i] = 0;
while (i - rad[i] > 0 && i + rad[i] + 1 < len && a[i - rad[i] - 1] == a[i + rad[i] + 1])
{
rad[i]++;
lp h = getHash((i - rad[i]) / 2 + 1, (i + rad[i] - 1) / 2 + 1);
if (!rad[i] && a[i] == '#' || map.count(h))
continue;
map[h] = 1;
ans++;
V.push_back(p((i - rad[i]) / 2, (i + rad[i] - 1) / 2));
}
if (i + rad[i] > mx)
mx = i + rad[i], pos = i;
}
printf("%d\n",ans);
k = m % ans + 1;
}
bool cmp(p a,p b)
{
int lena = a.second - a.first + 1;
int lenb = b.second - b.first + 1;
if (lena != lenb)
return lena < lenb;
int l = 1, r = lena;
while (l <= r)
{
int mid = (l + r) >> 1;
lp h1 = getHash(a.first + 1, a.first + mid);
lp h2 = getHash(b.first + 1, b.first + mid);
if (h1 == h2)
l = mid + 1;
else r = mid - 1;
}
return str[a.first + r] < str[b.first + r];
}
int main()
{
scanf("%d%lld",&n,&m);
scanf("%s",str);
pow1[0] = 1, pow2[0] = 1;
for (int i = 1; i <= n; i++)
{
hash1[i] = (1ll * hash1[i - 1] * POW1 + str[i - 1]) % MOD1;
hash2[i] = (1ll * hash2[i - 1] * POW2 + str[i - 1]) % MOD2;
pow1[i] = pow1[i - 1] * POW1 % MOD1;
pow2[i] = pow2[i - 1] * POW2 % MOD2;
}
manacher();
std::sort(V.begin(), V.end(), cmp);
for (int i = V[k - 1].first; i <= V[k - 1].second; i++)
putchar(str[i]);
putchar('\n');
}