zoukankan      html  css  js  c++  java
  • Manthan, Codefest 16 C. Spy Syndrome 2 字典树 + dp

    C. Spy Syndrome 2

    题目连接:

    http://www.codeforces.com/contest/633/problem/C

    Description

    After observing the results of Spy Syndrome, Yash realised the errors of his ways. He now believes that a super spy such as Siddhant can't use a cipher as basic and ancient as Caesar cipher. After many weeks of observation of Siddhant’s sentences, Yash determined a new cipher technique.

    For a given sentence, the cipher is processed as:

    Convert all letters of the sentence to lowercase.
    Reverse each of the words of the sentence individually.
    Remove all the spaces in the sentence.
    For example, when this cipher is applied to the sentence

    Kira is childish and he hates losing

    the resulting string is

    ariksihsidlihcdnaehsetahgnisol

    Now Yash is given some ciphered string and a list of words. Help him to find out any original sentence composed using only words from the list. Note, that any of the given words could be used in the sentence multiple times.

    Input

    The first line of the input contains a single integer n (1 ≤ n ≤ 10 000) — the length of the ciphered text. The second line consists of n lowercase English letters — the ciphered text t.

    The third line contains a single integer m (1 ≤ m ≤ 100 000) — the number of words which will be considered while deciphering the text. Each of the next m lines contains a non-empty word wi (|wi| ≤ 1 000) consisting of uppercase and lowercase English letters only. It's guaranteed that the total length of all words doesn't exceed 1 000 000.

    Output

    Print one line — the original sentence. It is guaranteed that at least one solution exists. If there are multiple solutions, you may output any of those.

    Sample Input

    30
    ariksihsidlihcdnaehsetahgnisol
    10
    Kira
    hates
    is
    he
    losing
    death
    childish
    L
    and
    Note

    Sample Output

    Kira is childish and he hates losing

    Hint

    题意

    你有一堆单词,然后把这一堆单词都翻转了,然后拼成了一个串。

    然后现在给你一个串,让你找到原来拼的那些单词是什么。

    题解:

    字典树+dp

    直接把那个串翻转一下,就相当于倒着做了嘛

    然后我们跑dp就好了,vis[i]表示这个位置能否被转移到

    然后我们就开始在字典树上面跑啊跑,看最远能够跑到哪儿,跑到了都打一个vis[i]=1,然后记录一个pre

    然后再倒着输出一个就完了。

    注意大小写……

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6+5;
    struct node{
        int ptr[26] , c ;
    };
    char s[maxn];
    int tot;
    int vis[maxn];
    int pre[maxn];
    node t[maxn];
    void init_node(node & f){
        memset(f.ptr , 0 , sizeof(f.ptr));
        f.c = 0;
    }
    void init(){
        tot = 1 ; init_node(t[0]);
    }
    inline int GetIdx(char ch){
        return ch - 'a';
    }
    void in(string str)
    {
        int cur = 0;
        for(int i = 0 ; i < str.size() ; ++ i)
        {
            int idx = GetIdx(str[i]);
            if(t[cur].ptr[idx])
                cur = t[cur].ptr[idx];
            else
            {
                init_node(t[tot]);
                cur = t[cur].ptr[idx] = tot ++ ;
            }
        }
        t[cur].c++;
    }
    void solve2(int x)
    {
        int o = x;
        x++;
        int cur=0,step=0;
        while(1)
        {
            int idx = GetIdx(s[x++]);
            if(t[cur].ptr[idx]) cur = t[cur].ptr[idx];
            else return;
            step ++;
            if(t[cur].c)vis[o+step]=1,pre[o+step]=o;
        }
    }
    int n,m;
    map<string,string> H;
    vector<string>ans;
    void solve1()
    {
        scanf("%d",&m);
    	while(m--)
    	{
            string s1,s2,s3;
            cin>>s1;
    		for(int i=0;i<s1.size();i++)
            {
    			s2+=s1[i];
    			if(s1[i]<='Z'&&s1[i]>='A')s1[i]=s1[i]+'a'-'A';
    			s3+=s1[i];
    		}
    		H[s3] = s2;
    		in(s1);
    	}
    }
    int main()
    {
        init();
        scanf("%d%s",&n,s+1);
        reverse(s+1,s+1+n);
        solve1();
        vis[0]=1;
        for(int i=0;i<n;i++)
            if(vis[i])
                solve2(i);
        while(n)
        {
            string tmp;
            for(int i=pre[n]+1;i<=n;i++)
                tmp+=s[i];
            ans.push_back(H[tmp]);
            n=pre[n];
        }
        for(int i=0;i<ans.size();i++)
            cout<<ans[i]<<" ";
        cout<<endl;
    }
  • 相关阅读:
    UITableview cell 的多选
    抽屉开关控制器
    NSDate 获取明天、后天的日期
    UITextField里面的 placeholder颜色和字体
    判断返回数据是否为 null
    UIButton 长按点击 背景改变效果
    UIButton 去除按下效果(阴影)
    iOS-RunLoop,为手机省电,节省CPU资源,程序离不开的机制
    iOS-真机调试
    iOS-设置启动图片
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5223572.html
Copyright © 2011-2022 走看看