Codeforces 633C Spy Syndrome 2(DP + Trie树)

题目大概说给一个加密的字符串,加密规则是把原文转化成小写字母,然后各个单词反转,最后去掉空格。现在给几个已知的单词,还原加密的字符串。

UVa1401一个道理。。

  • 用dp[i]表示加密字符前i个字符都被解密时,最后所用单词编号,为0表示不能被解密
  • 然后转移一个样,从i出发往前在Trie树上跑,看看能否找到不为0的dp[j],而str[j+1]str[j+2]...str[i-1]str[i]是单词
  • 最后输出方案就根据dp里面的值从最后面回溯找到并输出即可

时间复杂度O(加密字符串长*单词最大长度)。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<string>
 5 #include<algorithm>
 6 using namespace std;
 7 #define MAXN 1111111
 8 int tn,ch[MAXN][26],flag[MAXN];
 9 void insert(const char *s,int k){
10     int x=0,y;
11     for(int i=0; s[i]; ++i){
12         if(s[i]>='A' && s[i]<='Z') y=s[i]-'A';
13         else y=s[i]-'a';
14         if(ch[x][y]==0) ch[x][y]=++tn;
15         x=ch[x][y];
16     }
17     flag[x]=k;
18 }
19 
20 int d[11111];
21 char str[11111];
22 string word[110000];
23 void output(int n){
24     if(n<0) return;
25     output(n-word[d[n]].length());
26     cout<<word[d[n]]<<' ';
27 }
28 int main(){
29     int n,m;
30     scanf("%d%s%d",&n,str,&m);
31     for(int i=1; i<=m; ++i){
32         cin>>word[i];
33         insert(word[i].c_str(),i);
34     }
35     for(int i=0; i<n; ++i){
36         int x=0;
37         for(int j=i; j>=0; --j){
38             int y=str[j]-'a';
39             if(ch[x][y]==0) break;
40             x=ch[x][y];
41             if(flag[x] && (i-(i-j+1)<0 || d[i-(i-j+1)])){
42                 d[i]=flag[x];
43                 break;
44             }
45         }
46     }
47     output(n-1);
48     return 0;
49 }

 

posted @ 2016-07-15 16:38  WABoss  阅读(298)  评论(0编辑  收藏  举报