一个字符串t是半回文的条件是,对于所有的奇数 i(1≤i≤|t|+12),ti = t|t| − i + 1 始终成立,|t|表示字符串t的长度。下标从1开始。例如"abaa", "a", "bb", "abbbaa"都是半回文,而"ab", "bba"和"aaabaa"则不是。
现在有一个字符串s,只由小写字母a,b构成,还有一个数字k。现在要求找出s的半回文子串中字典序排在第k位的串,字符串可以是一样,只要所在的位置不同就是不一样的串。
样例解释:
这个样例中半回文子串是 a, a, a, a, aa, aba, abaa, abba, abbabaa, b, b, b, b, baab,bab, bb, bbab, bbabaab (按照字典序排序).
Input
单组测试数据。 第一行有一个字符串s(1 ≤ |s| ≤ 5000),只包含'a' 和 'b',|s|表示s的长度。 第二行有一个正整数k。k不超过s子串中是半回文串的总数目。
Output
输出排在第k位的半回文子串。
Input示例
abbabaab 7
Output示例
abaa
System Message
(题目提供者)
Visual C++的运行时限为:1000 ms ,空间限制为:262144 KB
示例及语言说明请按这里
允许其他 AC 的用户查看此代码,分享代码才能查看别人的代码并有机会获得勋章
题解:假如暴力找出所有子串并判断是否为半回文串,然后按照字典序排序的话是活在梦里,
然而怎么避免活在梦里呢,我们可以考虑字典树,将所有的回文子串加入字典树然后查询。
这样的话避免了排序的复杂度,但是还是够呛,还能怎么优化呢。对于每一个子串,我们可以
通过预处理找到所有合法的子串,并开一个vis数组表示当前位置能延伸到的最远的位置所能构成的
合法子串,这样的话时间复杂度便大大降低了。。。然后dfs找就好了。。(记得要按顺序)
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<math.h>
#include<time.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long ll;
#define inf 1000000000
#define mod 1000000007
#define maxn 6005
#define PI 3.1415926
#define lowbit(x) (x&-x)
#define eps 1e-9
char s[maxn * 1000];
string ans;
int dp[maxn][maxn], k, vis[maxn];
int siz, a[maxn * 1000][2], cnt[maxn * 1000][2];
void insert(int st)
{
int i, now = 0, len = strlen(s);
for (i = st;i <= vis[st];i++)
{
int v = s[i] - 'a';
if (a[now][v] == 0)
a[now][v] = ++siz;
if (dp[st][i])
cnt[now][v]++;
now = a[now][v];
}
}
void dfs(int x)
{
string tmp = ans;
if (k > 0 && a[x][0])
{
k -= cnt[x][0];
ans = ans + 'a';
dfs(a[x][0]);
}
if (k > 0 && a[x][1])
{
ans = tmp;
k -= cnt[x][1];
ans = ans + 'b';
dfs(a[x][1]);
}
}
int main(void)
{
int i, j;
scanf("%s", s);
scanf("%d", &k);
int len = strlen(s);
for (i = len-1;i >= 0;i--)
{
dp[i][i] = 1;
vis[i] = i;
for (j = i + 1;j < len;j++)
{
if (s[i] == s[j])
{
if (i + 2 >= j - 2)
dp[i][j] = 1;
else
dp[i][j] = dp[i + 2][j - 2];
}
if (dp[i][j])
vis[i] = j;
}
}
for (i = 0;i < len;i++)
insert(i);
dfs(0);
cout << ans << endl;
return 0;
}