poj 1816 (Trie + dfs)

题目链接:http://poj.org/problem?id=1816

思路:建好一颗Trie树,由于给定的模式串可能会重复,在原来定义的结构体中需要增加一个vector用来记录那些以该节点为结尾的字符串的序号,然后就是匹配的过程了,需要注意的是,对于‘?'和'*',每一次都是可以匹配的,并且对于'*',还得枚举所需要匹配的长度(从0开始)。由于最后的答案可能会有重复,一开始我没有判断时候有重复的,WA了好多次=.=!!.

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #define REP(i, a, b) for (int i = (a); i <= (b); ++i)
  7 using namespace std;
  8 
  9 const int MAN_N = (100000 + 100);
 10 struct Trie {
 11     int index;
 12     Trie *next[28];
 13     vector<int > ID; //可能会重复
 14     Trie()
 15     {
 16         index = -1;
 17         memset(next, 0, sizeof(next));
 18         ID.clear();
 19     }
 20 };
 21 
 22 Trie *root;
 23 int getID(char ch)
 24 {
 25     if (ch >= 'a' && ch <= 'z') return ch - 'a';
 26     else if (ch == '?') return 26;
 27     return 27;
 28 }
 29 void Insert(char *str, int pos)
 30 {
 31     int len = strlen(str);
 32     Trie *p = root;
 33     REP(i, 0, len - 1) {
 34         int id = getID(str[i]);
 35         if (p->next[id] == NULL) {
 36             p->next[id] = new Trie();
 37         }
 38         p = p->next[id];
 39     }
 40     p->index = pos;
 41     p->ID.push_back(pos);
 42 }
 43 int N, M;
 44 char str[22];
 45 vector<int > ans;
 46 
 47 void Check(Trie *&p)
 48 {
 49     if (p->next[27]) {
 50         if (p->next[27]->index != -1) {
 51             REP(i, 0, (int)p->next[27]->ID.size()-1) ans.push_back(p->next[27]->ID[i]);
 52         }
 53         Check(p->next[27]);
 54     }
 55 }
 56 
 57 
 58 void dfs(Trie *&p, int pos)
 59 {
 60     if (pos == N) {
 61         if (p->index != -1) {
 62             REP(i, 0, (int)p->ID.size()-1) {
 63                 ans.push_back(p->ID[i]);
 64             }
 65         }
 66         Check(p);
 67     } else {
 68         if (p->next[getID(str[pos])]) dfs(p->next[getID(str[pos])], pos + 1);
 69         if (p->next[26]) dfs(p->next[26], pos + 1);
 70         if (p->next[27]) {
 71             REP(i, pos, N) dfs(p->next[27], i);
 72         }
 73     }
 74 }
 75 
 76 
 77 int main()
 78 {
 79     cin >> N >> M;
 80     root = new Trie();
 81     REP(i, 0, N - 1) {
 82         scanf("%s", str);
 83         Insert(str, i);
 84     }
 85     REP(i, 0, M - 1) {
 86         scanf("%s", str);
 87         N = strlen(str);
 88         dfs(root, 0);
 89         if ((int)ans.size() > 0) {
 90             sort(ans.begin(), ans.end());
 91             printf("%d", ans[0]);
 92             REP(i, 1, (int)ans.size()-1) {
 93                 if (ans[i] != ans[i - 1]) printf(" %d", ans[i]);
 94             }
 95             puts("");
 96         } else
 97             puts("Not match");
 98         ans.clear();
 99     }
100     return 0;
101 }
View Code

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值