POJ 1816 Trie
链接:
http://poj.org/problem?id=1816
题意:
先给你n个字符串,这些字符串包含小写字母,‘?’和‘*’,其中
‘?’可以表示任意一个字符,‘*’可以表示任意长度的任意字符,包括0个
然后m次询问,每次给你一个字符串,问你它和哪些字符串匹配
题解:
5月第一发AC真不容易啊(其实上个月就该A的
这道题思路很简单,就是先建一个字典树,然后在字典树上跑dfs就好了,但是有几个需要注意的地方
当然如果方法不一样,可能就不会遇到这么多恶心的问题
首先最坑的就是题目中给的字符串会有一样的,所以就必须要用vector来存了
开始的时候dfs写错了,多写了一层循环,tle了
然后改完之后,wa了,发现是没有判断最后还有一个*的情况,然后加上之后又wa了
然后发现结尾可能不只有一个*,我的判断方式有问题,改好之后又wa了
忍不了就看了discuss,原来可能有重复的字符串,改成vector后结果又mle了。。。
果断把一个int数组改成short,然后又超时了。
大概是没加ios::sync_with_stdio(false), cin.tie(0);吧,加上之后继续wa。。
然后一想有重复的结点的话,直接输出是不行的(因为怕mle所以没有把答案先存下来)
虽然题目上没有说要排序输出,但既然不是special judge,还是要排序的,所以就只好先存了下来
然后排序,去重(我也不知道我为啥要去重,顺手去了0.0) 然后终于过了!!!
代码:
31 int pi = 1; 32 33 struct Node { 34 short next[30]; 35 VI id; 36 bool end; 37 }tree[MAXN * 6]; 38 39 void insert(string s, int id) { 40 int index, p, i; 41 for (i = p = 0; s[i]; i++) { 42 if (isalpha(s[i])) index = s[i] - 'a'; 43 else if (s[i] == '?') index = 26; 44 else index = 27; 45 if (tree[p].next[index] == 0) 46 tree[p].next[index] = pi++; 47 p = tree[p].next[index]; 48 } 49 tree[p].id.pb(id); 50 tree[p].end = 1; 51 } 52 53 VI ans; 54 55 void dfs(string s, int cnt, int p) { 56 if (cnt == s.length()) { 57 if (tree[p].end) 58 rep(i, 0, tree[p].id.size()) 59 ans.insert(ans.end(), all(tree[p].id)); 60 if (!tree[p].next[27]) return; 61 } 62 int index = s[cnt] - 'a'; 63 if (tree[p].next[index]) 64 dfs(s, cnt + 1, tree[p].next[index]); 65 if (tree[p].next[26]) 66 dfs(s, cnt + 1, tree[p].next[26]); 67 if (tree[p].next[27]) rep(j, cnt, s.size() + 1) 68 dfs(s, j, tree[p].next[27]); 69 } 70 71 int main() { 72 ios::sync_with_stdio(false), cin.tie(0); 73 int n, m; 74 cin >> n >> m; 75 rep(i, 0, n) { 76 string s; 77 cin >> s; 78 insert(s, i); 79 } 80 while (m--) { 81 ans.clear(); 82 string s; 83 cin >> s; 84 dfs(s, 0, 0); 85 sort(all(ans)); 86 ans.erase(unique(all(ans)), ans.end()); 87 if (ans.empty()) cout << "Not match"; 88 else rep(i, 0, ans.size()) cout << ans[i] << ' '; 89 cout << endl; 90 } 91 return 0; 92 }