Manthan, Codefest 16 C. Spy Syndrome 2(哈希+dp)

原题地址:http://codeforces.com/contest/633/problem/C

题意:给你m个单词的词典和一句话,这句话中的每个单词都来自字典,字典中的每一个单词重复可用,把这句话所有大写字母变成小写字母,然后反转单词去掉空格,要求你恢复这句话。

思路:这题做法好巧妙.我们先对单词进行预处理,存在 m a p 里面.因为要还原整个字符串,但是我们又不知道究竟单词断在哪里.所以我们就现需要确定单词断在哪里对于这个问题我们使用 D P 来判断, d p [ i ] = j 表示在i前面有一个单词,其哈希值是 j .最后倒着输出就行了.

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
string s, a;
int n, m;
ull dp[maxn];//dp[i]表示在i前面有单词,且其哈希值是dp[i]
unordered_map<ull, string>mp;
void dfs(int len) {
    if(len == 0) return;
    string str = mp[dp[len]];
    dfs(len - str.size());
    cout << str << " ";
}
int main() {
    ios::sync_with_stdio(false);
    cin >> n >> s >> m;
    for(int i = 1; i <= m; ++i) {
        cin >> a;
        string b = a;
        int len = a.size();
        ull tmp = 0;
        for(int j = 0; j < len; ++j) {
            tmp = tmp * seed + tolower(a[j]);
        }
        mp[tmp] = b;
    }
    CLR(dp, -1);
    dp[0] = 0;
    for(int i = 0; i < n; ++i) {
        ull tmp = 0;
        for(int j = i; j >= 0; --j) {
            tmp = tmp * seed + s[j];
            if(dp[j] != -1 && mp.count(tmp)) {
                dp[i + 1] = tmp;
                break;
            }
        }
    }
    dfs(n);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81540416
今日推荐