Technorati 标签: 数据结构与算法 看了一遍,题目本身并不难,容易想到用Trie树。对哪个建立Trie树,显然对后面的串建立是不太合适的,因为0 < N <= 100000,对前面的建立Trie树,还是得考虑一些细节之处,主要是dfs时需要考虑清楚递归条件,避免疏漏和重复。我写的时候错了一个,后来参考了这个. 判重还是很必要的,比如 4 2t*h*wm?h*s*w*h*w*j*j jjj 因为*j*是一次,*j*j是一次,导致有两个3,输出时去除,或者弄个数组判重。 //POJ1816 #include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; const int KEYSIZE = 28; const int MATCH_ANY = 26; //* const int MATCH_ONE = 27; //? const int MAXN = 21; class TrieNode { public: std::vector <int> ids;//记录id号 //char data; TrieNode* branch[KEYSIZE]; TrieNode() { memset (branch, 0, sizeof (TrieNode*) * KEYSIZE); } ~TrieNode() { for (int i = 0; i < KEYSIZE; ++i) { delete branch[i]; } } }; typedef std::vector<int> ResultSet; class Trie { private: TrieNode *root; public: Trie() { root = new TrieNode(); } void insert(const char *str, int id); void query(const char *str, ResultSet &rs); private: void dfsQuery(TrieNode *node, const char *str, ResultSet &rs, int depth); }; void Trie::dfsQuery(TrieNode *node, const char *str, ResultSet &rs, int depth) { if (str[depth] == '/0') //终止 { while (NULL != node) { rs.reserve(rs.size() + node->ids.size()); for (int i = 0; i < node->ids.size(); ++i) rs.push_back(node->ids[i]); node = node->branch[MATCH_ANY]; } } else { int pick = str[depth] - 'a'; if (NULL != node->branch[pick]) dfsQuery(node->branch[pick], str, rs, depth + 1); if (node->branch[MATCH_ONE]) //? { dfsQuery(node->branch[MATCH_ONE], str, rs, depth + 1); } if (node->branch[MATCH_ANY]) //* { //如果用以下两行会产生重复 //dfsQuery(node, str, rs, depth + 1); //dfsQuery(node->branch[MATCH_ANY], str, rs, depth + 1); int i; for (i = depth; str[i] != '/0'; ++i) // { dfsQuery(node->branch[MATCH_ANY], str, rs, i); } dfsQuery(node->branch[MATCH_ANY], str, rs, i); //需要考虑终止的情况,因此不能丢掉'/0' } } } void Trie::query(const char *str, ResultSet &rs) { dfsQuery(root, str, rs, 0); } void Trie::insert(const char *str, int id) { TrieNode* node = root; int i = 0; while (str[i] != '/0') { int pick = 0; if (str[i] >= 'a' && str[i] <= 'z') pick = str[i] - 'a'; else if (str[i] == '?') pick = MATCH_ONE; else pick = MATCH_ANY; if (NULL == node->branch[pick]) { node->branch[pick] = new TrieNode; } node = node->branch[pick]; ++i; } node->ids.push_back(id); } int main() { Trie trie; //freopen("G:/acm/pku1816.txt", "r", stdin); int n, m; scanf("%d %d", &n, &m); char str[MAXN]; for (int i = 0; i < n; ++i) { scanf("%s", str); trie.insert(str, i); } ResultSet rs; for (int i = 0; i < m; ++i) { scanf("%s", str); rs.clear(); trie.query(str, rs); if (rs.empty()) { printf("Not match/n"); } else { std::sort(rs.begin(), rs.end()); //int countMinusOne = rs.size() - 1; printf("%d", rs[0]); for (int i = 1; i < rs.size(); ++i) { if (rs[i] != rs[i - 1]) printf(" %d", rs[i]); } printf("/n", rs.back()); } } return 0; }