• 2020 camp day2 -k


    题面

    7-11 2K. 破忒头的匿名信

    破忒头想要写一封匿名信来做坏事,由于他不想被认出自己的笔迹,因此他想要雇佣萨博来帮他写这封信。萨博按照这样的标准来收费:他的词典里有N个单词,第i个单词的单价是p​i​​。如果你提供一个长度为M的序列,,那么你需要支付∑​i=1​M​​p​a​i​​​​的金钱,而萨博会依次往信里写上。破忒头希望支付最少的金钱,让萨博写的内容恰好为他想要的信件内容T。请你告诉破忒头,最少需要付多少钱,能让萨博写出他想要的匿名信,或者告诉他这是不可能做到的。

    输入格式:

    对于每组测试数据,第一行包含一个正整数N,表示萨博词典里的单词个数(1)。接下来的N行描述词典里的每个单词,第i行包含一个字符串Si​​和这个字符串的单价pi​​(1)。接下来一行包含破忒头想要的信件内容T(1)。保证Si​​和T都仅包含小写字母,且Si​​的总长度不超过5。

    输出格式

    如果有可能让萨博写出破忒头想要的信件内容,那么输出一个正整数,表示最小需要付出的代价。否则,输出-1。

    输入样例:

    4
    ab 5
    cd 10
    abc 100
    d 1
    abcd
    
     
    1
    ab 1
    abc
    
     

    输出样例:

    15
    
     
    -1

    作者: 2020,Winter,Day2
    单位: 东北大学秦皇岛分校
    时间限制: 5000 ms
    内存限制: 256 MB
    代码长度限制: 16 KB
     

    题解

    基本的ac自动机构造 + DAG上dp

    注意insert时,不像以往,对于重复字串,我们只更新其价格使其价格最低,即每个结尾至多只有一个字符串结尾,并记录下这个字符串的长度(深度)。

    对于query,不再查询有多少个字串,直接开始dp,有点像01背包,但有所不同。

    其他都是细节。

    代码如下

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    #define RE register
    #define FOR(i,a,b) for(RE int i=a;i<=b;++i)
    #define ROF(i,a,b) for(int i=a;i>=b;--i)
    #define ll long long 
    #define sc(x) scanf("%d",&x)
    #define ss(s) scanf("%s",s)
    
    using namespace std;
    
    const int MAXN = 5e5 + 10;
    const int inf = 0x3f3f3f3f;
    const int C = 'a';
    const int M = 26;
    
    int n, len, cost;
    char s[MAXN];
    ll d[MAXN];
    
    struct ac
    {
        int trie[MAXN][M], fail[MAXN], lenth[MAXN], vis[MAXN];
        ll val[MAXN];
        int q[MAXN], tot;
    
        void insert(char* s, ll v)
        {
            int p = 0;
            for (RE int i = 0; s[i]; ++i)
            {
                int ch = s[i] - C;
                if (!trie[p][ch])trie[p][ch] = ++tot; 
                p = trie[p][ch];
                lenth[p] = i + 1;
            }
            if (val[p])val[p] = min(val[p], v);
            else val[p] = v;
        }
    
        void build()
        {
            int head = 0, tail = -1;
            FOR(i, 0, M - 1)
                if (trie[0][i])
                    q[++tail] = trie[0][i];
            while (head <= tail)
            {
                int p = q[head++];
                FOR(i, 0, M - 1)
                    if (trie[p][i])
                        fail[trie[p][i]] = trie[fail[p]][i],
                        q[++tail] = trie[p][i];
                    else trie[p][i] = trie[fail[p]][i];
            }
        }
    
        void  query(char* s)
        {
            int p = 0;
            for (RE int i = 0; s[i]; ++i)
            {
                p = trie[p][s[i] - C];
                for (RE int tmp = p; tmp; tmp = fail[tmp])
                {
                    if (vis[i - lenth[tmp] + 1] && val[tmp])
                    {
                        d[i + 1] = min(d[i + 1], d[i - lenth[tmp] + 1] + val[tmp]);
                        vis[i + 1] = 1;
                    }
                }
            }
        }
    }a;
    
    int main()
    {
        sc(n);
        FOR(i, 1, n)
        {
            ss(s); sc(cost);
            a.insert(s, cost);
        }
        a.build();ss(s);
        len = strlen(s);
        a.vis[0] = 1;
        for (RE int i = 1; i <= len; ++i)
            d[i] = 1ll * inf * inf;
        a.query(s);
        if (!a.vis[len])puts("-1");
        else printf("%lld
    ", d[len]);
        return 0;
    }
    

      

     
  • 相关阅读:
    渣渣的python的上路
    【tyvj 2038】诡异的数学题
    codeforces_733_A
    NOIP2011 选择客栈
    NOIP 2012 同余方程
    灵渊(seals.cpp/c/pas)
    NOIP 2012 开车旅行
    Mybatis初步详细配置
    SpringMVC之编程式校验
    Spring整合MyBaytis
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12194209.html
Copyright © 2020-2023  润新知