您的位置:首页 > 其它

51nod 1464 半回文(dp,Trie)

2017-09-26 20:42 453 查看
参考题解:http://blog.csdn.net/haut_ykc/article/details/77933792

第一发是把所有半回文串放进了字典树,搜一发,半回文串是暴力找的,有两组数据超时。

看这个题解讲的挺好,用dp对半回文串预处理,dp[i][j]==true表示i开头的子串,以j结尾的子串是个半回文串,vis[i]表示以i开头的半回文串最远能够延伸到哪个位置。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 6005;
char s[MAXN];
string ans;
bool dp[MAXN][MAXN];
int k,vis[MAXN];
int siz,Trie[MAXN*1000][2];
int num[MAXN*1000];

void insert(int st)
{
int i, now = 0;
for (i = st; i <= vis[st]; i++)
{
int v = s[i] - 'a';
if (Trie[now][v] == 0)
Trie[now][v] = ++siz;
if (dp[st][i])
num[Trie[now][v]]++;
now = Trie[now][v];
}
}

void dfs(int x)
{
string tmp = ans;
if (k > 0 && Trie[x][0])
{
k -= num[Trie[x][0]];
ans = ans + 'a';
dfs(Trie[x][0]);
}
if (k > 0 && Trie[x][1])
{
ans = tmp;
k -= num[Trie[x][1]];
ans = ans + 'b';
dfs(Trie[x][1]);
}
}

void init(int len)
{
for (int i = len-1; i >= 0; i--)
{
dp[i][i] = true;
vis[i] = i;
for (int 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;
}
}
}

int main(void)
{
scanf("%s", s);
scanf("%d", &k);
int len = strlen(s);
init(len);
for (int i = 0; i < len; i++)
insert(i);
dfs(0);
cout << ans << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: