CF #Manthan, Codefest 16 C. Spy Syndrome 2 Trie

题目链接:http://codeforces.com/problemset/problem/633/C

大意就是给个字典和一个字符串,求一个用字典中的单词恰好构成字符串的匹配。

比赛的时候是用AC自动机写的,就是对于trie中每一个节点,判断是否为终结点,以及当前字符所在位置p减去trie中这个节点的深度也即某一单词的长度l,判断dp[p-l]是否可以被构成,可以的话直接break并且标记当前dp值。

 

赛后想了想,其实直接一个trie就行了,每个单词才1000的长度,又想起来我去年给人讲过类似的问题,当时我自己非常清楚这种单词构成用个简单的tire来搞就行。怎么比赛的时候就写了个AC自动机了呢。

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <string>
 5 #include <string.h>
 6 #include <stdio.h>
 7 #include <math.h>
 8 #include <stdlib.h>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #include <ctime>
14 #include <numeric>
15 #include <cassert>
16 
17 using namespace std;
18 const int N=100001;
19 string dic[N];
20 char str[N],pat[N];
21 int mark[N];
22 const int CHARSET=26,BASE='a',MAX_NODE=1000001;
23 struct Trie {
24     int tot,root,child[MAX_NODE][CHARSET];
25     int flag[MAX_NODE];
26     Trie(){
27         init();
28     }
29     void init(){
30         root=newNode();
31     }
32     int newNode() {
33         ++tot;
34         memset(child[tot],0,sizeof(child[tot]));
35         flag[tot]=0;
36         return tot;
37     }
38     void insert(const char *str,int id){
39         int *cur=&root;
40         for (const char *p=str;*p;++p){
41             cur=&child[*cur][*p-BASE];
42             if (*cur==0)
43                 *cur=newNode();
44         }
45         flag[*cur]=id;
46     }
47     void query(int x){
48         int *cur=&root;
49         for (int i=x;i>=1;i--){
50             char ch=str[i];
51             cur=&child[*cur][ch-BASE];
52             if ((*cur)==0) break;
53             if (flag[*cur]&&mark[i-1]!=-1){
54                 mark[x]=flag[*cur];
55                 break;
56             }
57         }
58     }
59 }trie;
60 int main () {
61     int n;
62     scanf("%d",&n);
63     scanf("%s",str+1);
64     int m;
65     scanf("%d",&m);
66     for (int i=1;i<=m;i++) {
67         scanf("%s",pat);
68         dic[i]=string(pat);
69         int len=dic[i].length();
70         for (int j=0;j<=len;j++)
71             if (pat[j]>='A'&&pat[j]<='Z')
72                 pat[j]+='a'-'A';
73         trie.insert(pat,i);
74     }
75     memset(mark,-1,sizeof mark);
76     mark[0]=0;
77     for (int i=1;i<=n;i++){
78         trie.query(i);
79     }
80     vector<int> ret;
81     int now=n;
82     while (now>0) {
83         ret.push_back(mark[now]);
84         now-=dic[mark[now]].length();
85     }
86     for (int i=(int)ret.size()-1;i>=0;i--) {
87         printf("%s ",dic[ret[i]].c_str());
88     }
89     return 0;
90 }
View Code

 

posted @ 2016-02-29 23:28  活在夢裡  阅读(251)  评论(0编辑  收藏  举报