51nod1464(trie + dfs)
Posted ygeloutingyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1464(trie + dfs)相关的知识,希望对你有一定的参考价值。
题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1464
题意: 中文题诶~
思路: 将所有半回文串构建成一棵字典树, 再 dfs 里面字典序第 k 大的字符串.
注意插入半回文串时不能完全暴力插入, 不然插入的时间复杂度为 O(n^3), 会 tle. 可以先用 dp 预处理一下, dp[i][j] 存储 子串[i, j] 是否为回文串, vis[i] 记录以 i 开头的最长半回文串末尾位置. 那么插入时可以每次插入 [i, vis[i]] 之间的所有半回文串, 时间复杂度为 O(n^2). 然后再 dfs 一下答案即可.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 6 const int MAXN = 5e3 + 10; 7 int trie[MAXN * MAXN][2], num[MAXN * MAXN], id = 1; 8 bool dp[MAXN][MAXN];//dp[i][j]存储[i,j] 是否为半回文串 9 int vis[MAXN];//vis[i]存储以i开始的最长半回文串末尾位置 10 char s[MAXN]; 11 12 void init(int len){ 13 for(int i = len - 1; i >= 0; i--){ 14 vis[i] = i; 15 dp[i][i] = true; 16 for(int j = i + 1; j < len; j++){ 17 if(s[i] == s[j]){ 18 if(i + 2 >= j - 2) dp[i][j] = true; 19 else dp[i][j] = dp[i + 2][j - 2]; 20 } 21 if(dp[i][j]) vis[i] = j; 22 } 23 } 24 } 25 26 void insert(int st){ 27 int node = 0; 28 for(int i = st; i <= vis[st]; i++){ 29 int cnt = s[i] - ‘a‘; 30 if(!trie[node][cnt]) trie[node][cnt] = id++; 31 if(dp[st][i]) num[trie[node][cnt]]++; 32 node = trie[node][cnt]; 33 } 34 } 35 36 int k; 37 string sol; 38 39 void dfs(int x){ 40 string cnt = sol; 41 if(k > 0 && trie[x][0]){ 42 sol += ‘a‘; 43 k -= num[trie[x][0]]; 44 dfs(trie[x][0]); 45 } 46 if(k > 0 && trie[x][1]){ 47 sol = cnt; 48 sol += ‘b‘; 49 k -= num[trie[x][1]]; 50 dfs(trie[x][1]); 51 } 52 } 53 54 int main(void){ 55 scanf("%s%d", s, &k); 56 int len = strlen(s); 57 init(len); 58 for(int i = 0; i < len; i++){ 59 insert(i); 60 } 61 dfs(0); 62 cout << sol << endl; 63 return 0; 64 }
以上是关于51nod1464(trie + dfs)的主要内容,如果未能解决你的问题,请参考以下文章
51Nod1601 完全图的最小生成树计数 Trie Pruffer编码
51nod 1295 XOR key (可持久化Trie树)