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开头的半回文串最远能够延伸到哪个位置。
第一发是把所有半回文串放进了字典树,搜一发,半回文串是暴力找的,有两组数据超时。
看这个题解讲的挺好,用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; }
相关文章推荐
- 51nod 1092 回文字符串 (dp)
- 51nod 1464 半回文(字典树+DFS+预处理)
- 51Nod 1092 回文字符串(LCS跟dp)
- 51Nod-1464-半回文
- 【51nod 1092】 回文字符串(区间DP)
- 51nod 1092 回文字符串 LCS 或 区间dp
- 51nod 1092 回文字符串 dp问题
- 51nod 1464 半回文
- 51nod 1092 回文字符串(区间dp)
- 51nod 1503 猪和回文(双线DP)
- 51nod 1503 猪和回文(dp)
- 51Nod 1092 回文字符串(LCS跟dp)
- 51nod 1092 回文字符串 【巧用 dp】
- 51nod 1092 回文字符串 (LCS_DP)
- 51nod 1503 猪和回文【DP】
- UVa 10617 Again Palindrome(回文 区间dp)
- 51nod-正整数分组问题(基础方程DP-01背包)
- 51Nod-1503-猪和回文
- 51Nod 1391 DP + Hash
- 51nod 1092 回文字符串 (添加几个变成回文)