问题描述
- 这道题目用C++怎么做?
-
一个字符串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 (按照字典序排序).
解决方案
我们可以先考虑O(n^2)预处理出所有的半回文串.我们假设DP[i][j]=true表示子串s[i,j]是半回文子串,反之,不是半回文子串.那么可以得出dp[i+2][j-2]也是半回文串,所以可以得出状态转移方程dp[i][j]=dp[i+2][j-2]. 然后可以考虑以s[i]开头的所有半回文串,建一棵Trie(字典树),然后就可以通过DFS搜索出第k小的半回文子串.这部分的时间复杂度也为kO(n^2),所以总的算法时间复杂度为kO(n^2).k为字符串的字符种类.
解决方案二:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 5005;
char s[N];
int k,n,l,r;
bool dp[N][N];
int vis[N];
string ans;
struct Tree
{
Tree()
{
val = 0;
memset(next,0,sizeof next);
}
int val;
Tree *next[2];
}*tree_head;
void init()
{
tree_head = new Tree();
n = strlen(s);
memset(dp,false,sizeof dp);
for(int i = n - 1; i >= 0; --i)
{
dp[i][i] = true;
vis[i] = i;
for(int j = i + 1; j < n; ++j)
{
if(s[i] == s[j])
{
if(i + 2 >= j - 2)
dp[i][j] = true;
else dp[i][j] = dp[i + 2][j - 2];
}
if(dp[i][j]) vis[i] = j;
}
}
}
void insert_tree(Tree *ptemp, char *s)
{
if(*s == '') return;
if(r > vis[l]) return;
int c = *s - 'a';
if(ptemp->next[c] == NULL)
ptemp->next[c] = new Tree();
if(dp[l][r]) ptemp->next[c]->val++;
r++;
insert_tree(ptemp->next[c], s + 1);
}
void dfs(Tree *ptemp)
{
string temp = ans;
if(k > 0 && ptemp->next[0])
{
k -= ptemp->next[0]->val;
ans = ans + 'a';
dfs(ptemp->next[0]);
}
if(k > 0 && ptemp->next[1])
{
ans = temp;
k -= ptemp->next[1]->val;
ans = ans + 'b';
dfs(ptemp->next[1]);
}
}
void solve()
{
scanf("%s %d",s,&k);
init();
for(int i = 0; i < n; ++i)
{
l = r = i;
insert_tree(tree_head,s + i);
}
dfs(tree_head);
cout << ans << endl;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
solve();
return 0;
}
解决方案三:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 5005;
char s[N];
int k,n,l,r;
bool dp[N][N];
int vis[N];
string ans;
struct Tree
{
Tree()
{
val = 0;
memset(next,0,sizeof next);
}
int val;
Tree *next[2];
}*tree_head;
void init()
{
tree_head = new Tree();
n = strlen(s);
memset(dp,false,sizeof dp);
for(int i = n - 1; i >= 0; --i)
{
dp[i][i] = true;
vis[i] = i;
for(int j = i + 1; j < n; ++j)
{
if(s[i] == s[j])
{
if(i + 2 >= j - 2)
dp[i][j] = true;
else dp[i][j] = dp[i + 2][j - 2];
}
if(dp[i][j]) vis[i] = j;
}
}
}
void insert_tree(Tree *ptemp, char *s)
{
if(*s == '') return;
if(r > vis[l]) return;
int c = *s - 'a';
if(ptemp->next[c] == NULL)
ptemp->next[c] = new Tree();
if(dp[l][r]) ptemp->next[c]->val++;
r++;
insert_tree(ptemp->next[c], s + 1);
}
void dfs(Tree *ptemp)
{
string temp = ans;
if(k > 0 && ptemp->next[0])
{
k -= ptemp->next[0]->val;
ans = ans + 'a';
dfs(ptemp->next[0]);
}
if(k > 0 && ptemp->next[1])
{
ans = temp;
k -= ptemp->next[1]->val;
ans = ans + 'b';
dfs(ptemp->next[1]);
}
}
void solve()
{
scanf("%s %d",s,&k);
init();
for(int i = 0; i < n; ++i)
{
l = r = i;
insert_tree(tree_head,s + i);
}
dfs(tree_head);
cout << ans << endl;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
solve();
return 0;
}
解决方案四:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int N = 5005;
char s[N];
int k,n,l,r;
bool dp[N][N];
int vis[N];
string ans;
struct Tree
{
Tree()
{
val = 0;
memset(next,0,sizeof next);
}
int val;
Tree *next[2];
}*tree_head;
void init()
{
tree_head = new Tree();
n = strlen(s);
memset(dp,false,sizeof dp);
for(int i = n - 1; i >= 0; --i)
{
dp[i][i] = true;
vis[i] = i;
for(int j = i + 1; j < n; ++j)
{
if(s[i] == s[j])
{
if(i + 2 >= j - 2)
dp[i][j] = true;
else dp[i][j] = dp[i + 2][j - 2];
}
if(dp[i][j]) vis[i] = j;
}
}
}
void insert_tree(Tree *ptemp, char *s)
{
if(*s == '') return;
if(r > vis[l]) return;
int c = *s - 'a';
if(ptemp->next[c] == NULL)
ptemp->next[c] = new Tree();
if(dp[l][r]) ptemp->next[c]->val++;
r++;
insert_tree(ptemp->next[c], s + 1);
}
void dfs(Tree *ptemp)
{
string temp = ans;
if(k > 0 && ptemp->next[0])
{
k -= ptemp->next[0]->val;
ans = ans + 'a';
dfs(ptemp->next[0]);
}
if(k > 0 && ptemp->next[1])
{
ans = temp;
k -= ptemp->next[1]->val;
ans = ans + 'b';
dfs(ptemp->next[1]);
}
}
void solve()
{
scanf("%s %d",s,&k);
init();
for(int i = 0; i < n; ++i)
{
l = r = i;
insert_tree(tree_head,s + i);
}
dfs(tree_head);
cout << ans << endl;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
solve();
return 0;
}
解决方案五:
这道题目你会做吗?