HDU 2340 Obfuscation (DP--记忆话搜索)

101 篇文章 1 订阅
17 篇文章 0 订阅

大体题意:

给你一个包含n 个单词的字典,给你一篇文章,文章包括若干词典里的单词,把句子里的空格都去掉,单词的首位字母都不变,中间的字符集为乱序,问能否恢复这篇文章,使得单词都是词典里的单词,如果有唯一解,输出唯一解!

思路:

令dp[i]表示从i位置开始到最后一个位置 的解释数量。

我们可以采用记忆话搜索的形式!

可以用unordered_map<string,vector<int> >  无序map 来存  中间字符排序后对应的原单词!

为了优化 我们可以 找到最长单词的长度,在记忆话搜索中  直接从当前位置i  枚举单词,如果在map 中存在  就继续dfs。

最后说说统计路径!

路径肯定都是dp[i] = 1的,那么在dfs 中 发现ans 加的值是1的话,就记录一下单词!

教训:

1.  枚举单词时如果 边构造边排序的话,会超时! 应该插入一个字符 二分找到插入的位置 插进去,这样会快不少!

2.  在记录单词时,只有在ans加的值是1的话才记录单词,否则会被覆盖掉(WA了好几次= =)

详细见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <unordered_map>
#define max(a,b) (a) > (b) ? (a) : (b)
using namespace std;
const int maxn = 1000 + 10;
char s[maxn],tab[10007][107];
int dp[maxn];
int len;
unordered_map<string,vector<int> >mp;
string nest[maxn];
int Maxlen;
int dfs(int k){
//    printf("^^^^ k = %d\n",k);
    int& ans = dp[k];
    if (~ans) return ans;
    if (k >= len) return ans = 1;
    ans = 0;
    string t2 = "";
    for (int i = k; i < len && i-k+1 <= Maxlen; ++i){
        if (t2.length() >= 3){
            char ch = t2[t2.length()-1];
            t2.erase(t2.end()-1);
            t2.insert(lower_bound(t2.begin()+1,t2.end(),ch),ch);
        }
        t2+=s[i];
//        printf("&&& %s\n",t2.c_str());
        if (mp.count(t2)){
//            printf ("the string is ok  is : %s\n",t2.c_str());
            int tmpp = dfs(k+t2.length()) * (int)mp[t2].size();
            ans += tmpp;
            if (tmpp == 1){
                nest[k] = tab[mp[t2].front()];
            }
            if (ans > 1){
                break;
            }
        }


    }
    return ans;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        mp.clear();
        memset(dp,-1,sizeof dp);
        Maxlen = 0;
//        for (int i = 0; i < 30; ++i) g[i].clear();
        scanf("%s",s);
        len = strlen(s);
        scanf("%d",&n);
        for (int i = 0; i < n; ++i){
            scanf("%s",tab[i]);
            string tmp(tab[i]);
            if (tmp.length() > 3) sort(tmp.begin()+1,tmp.end()-1);
            mp[tmp].push_back(i);
//            printf("tmp = %s\n",tmp.c_str());
            Maxlen = max(Maxlen,(int)tmp.length());
        }
        int ans = dfs(0);
        if (!ans)puts("impossible");
        else if (ans > 1)puts("ambiguous");
        else {
            int l = 0;
            int cnt2 = 0;
            while(l < len){
                if (cnt2++)printf(" ");
                printf("%s",nest[l].c_str());
                l = l + nest[l].length();
            }
            puts("");
        }
    }
    return 0;
}
/**

3
tihssnetnceemkaesprfecetsesne
5
makes
perfect
sense
sentence
this
hitehre
2
there
hello
hitehre
3
hi
there
three

**/


Obfuscation

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 288    Accepted Submission(s): 68


Problem Description
It is a well-known fact that if you mix up the letters of a word, while leaving the first and last letters in their places, words still remain readable. For example, the sentence “tihs snetncee mkaes prfecet sesne”, makes perfect sense to most people.

If you remove all spaces from a sentence, it still remains perfectly readable, see for example: “thissentencemakesperfectsense”, however if you combine these two things, first shuffling, then removing spaces, things get hard. The following sentence is harder to decipher: “tihssnetnceemkaesprfecetsesne”.

You’re given a sentence in the last form, together with a dictionary of valid words and are asked to decipher the text.

 

Input
On the first line one positive number: the number of testcases, at most 100. After that per testcase:

One line with a string s: the sentence to decipher. The sentence consists of lowercase letters and has a length of at least 1 and at most 1 000 characters.

One line with an integer n with 1 ≤ n ≤ 10 000: the number of words in the dictionary.

n lines with one word each. A word consists of lowercase letters and has a length of at least 1 and at most 100 characters. All the words are unique.
 

Output
Per testcase:

One line with the deciphered sentence, if it is possible to uniquely decipher it. Otherwise “impossible” or “ambiguous”, depending on which is the case.
 

Sample Input
  
  
3 tihssnetnceemkaesprfecetsesne 5 makes perfect sense sentence this hitehre 2 there hello hitehre 3 hi there three
 

Sample Output
  
  
this sentence makes perfect sense impossible ambiguous
 

Source
 

Recommend
zty   |   We have carefully selected several similar problems for you:   2333  2339  2342  2341  2334 
 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值