CF633C Spy Syndrome 2

嘟嘟嘟

题面:把一句话加密:1.所有字母变成小写。2.翻转所有单词。3.去掉空格。然后给你一句加密后的字符串以及一些出现在原句和没有出现在原句的单词,让你还原原句。注意,每一个单词可以使用多次,如果有多个答案,输出其中任意一个。

trie树好题……

首先都能想到的是把所有单词建成一棵trie树,然后我是这么想的,对于加密后字符串,每句每一个字符作为单词结尾,然后倒着再trie树上跑,知道遇到一个单词,记录是第几个,最后输出。

但是这样是不对的,因为无法保证遇到一个单词后,这个单词之前的部分已经匹配好了,举个例子:High,加密后是hgih,然后给定的单词有 hi 和 high,当扫到最后一个字符'h'的时候,在trie树上得到的第一个单词是 hi,而hi之前的gh无法构成一个单词,所以gg。

因此,我们还要有一个pre数组,记录每一个匹配点的上一个是由哪一个匹配点转移过来的,在trie树上跑的时候,只有当前点构成一个单词,且这个单词的前一个字符是匹配点,才return。

最后沿着pre数组找到头,倒叙输出。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<stack>
 9 #include<queue>
10 #include<vector>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 1e4 + 5;
21 const int maxm = 1e5 + 5;
22 inline ll read()
23 {
24   ll ans = 0;
25   char ch = getchar(), las = ' ';
26   while(!isdigit(ch)) las = ch, ch = getchar();
27   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
28   if(las == '-') ans = -ans;
29   return ans;
30 }
31 inline void write(ll x)
32 {
33   if(x < 0) putchar('-'), x = -x;
34   if(x >= 10) write(x / 10);
35   putchar(x % 10 + '0');
36 }
37 
38 int n, m;
39 char s[maxn], ss[maxm][1005];
40 
41 int cnt = 0;
42 struct Trie
43 {
44   int ch[26], val;
45   Trie()
46   {
47     Mem(ch, 0); val = 0;
48   }
49 }t[maxm * 10];
50 int getnum(char c)
51 {
52   return c >= 'a' ? c - 'a' : c - 'A';
53 }
54 void insert(int id, char *s)
55 {
56   int len = strlen(s);
57   for(int i = 0, now = 0; i < len; ++i)
58     {
59       int c = getnum(s[i]);
60       if(!t[now].ch[c]) t[now].ch[c] = ++cnt;
61       now = t[now].ch[c];
62       if(i == len - 1) t[now].val = id;
63     }
64 }
65 
66 int ans[maxn], pre[maxn];
67 void query(int x)
68 {
69   for(int i = x, now = 0; i >= 0; --i)
70     {
71       int c = getnum(s[i]);
72       if(!t[now].ch[c]) return;
73       now = t[now].ch[c];
74       if(t[now].val && (ans[i - 1] || i == 0)) {pre[x] = i - 1, ans[x] = t[now].val; return;}
75     }
76   return;
77 }
78 
79 
80 void print(int x)
81 {
82   if(pre[x] != -1) print(pre[x]);
83   printf("%s ", ss[ans[x]]);
84 }
85 
86 int main()
87 {
88   n = read(); scanf("%s", s);
89   m = read();
90   for(int i = 1; i <= m; ++i)
91     {
92       scanf("%s", ss[i]);
93       insert(i, ss[i]);
94     }
95   for(int i = 0; i < n; ++i) query(i);
96   print(n - 1); enter;
97   return 0;
98 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9767199.html