zoukankan      html  css  js  c++  java
  • poj 3267 The Cow Lexicon 动态规划

    题目链接:http://poj.org/problem?id=3267

    给一个字典

    求原串中至少去掉多少个字母可以让已给字典可以完整覆盖原串

    在跟字典作匹配时 注意原串是“可跳跃的” 即存在“删掉某个字母后 该字母的前后两部分拼起来组成单词”

    针对这种情况 考虑使用两个指针

    匹配时:同时往后滑1格

    不匹配时:仅指向原串的指针往后滑1格

    之所以网上大部分题解都是从原串的最后往前推

    是因为这样写起来下标容易控制 

    最外层循环的原串从后往前 则匹配过程可以较自然地从前往后 而匹配过程明显更为复杂 所以这种写法有它的道理

    pt1指向原串的字符位置

    pt2指向字典中的单词的字符位置

    状态转移方程:

    在原串中没有以当前字符开头且可与字典匹配的单词时 dp[i] = dp[i+1]+1

    在原串中有以当前字符开头且可与字典匹配的单词时 dp[i] = min(dp[i], dp[pt1] + (pt1 - i) - pt2) 不断更新 其中 “(pt1 - i) - pt2”表示为了得到匹配而删掉的字符数

    这样dp[0]即为答案

    这题也是本来有用string类 写着写着觉得没必要 就改掉了 

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <set>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    const int maxlen = 320;
    const int maxn = 610;
    
    typedef struct
    {
        char s[maxlen];
        int len;
    }Node;
    
    Node check[maxn];
    char tmp[maxlen];
    int dp[maxlen];
    char a[maxn];
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
    
        int w, l;
        scanf("%d%d", &w, &l);
    
        dp[l] = 0;
    
        scanf("%s", a);
        for(int i = 0; i < w; i++)
        {
            scanf("%s", tmp);
            strcpy(check[i].s, tmp);
            check[i].len = strlen(tmp);
        }
    
        for(int i = l-1; i >= 0; i--)
        {
            dp[i] = dp[i+1]+1;//先赋值过来 等后面不断更新 
            bool flag = false;
    
            for(int t = 0; t < w; t++)
            {
                int tmplen = l - i + 1;
    
                if(check[t].len <= tmplen && check[t].s[0] == a[i])
                {
                    int pt1 = i;//指向a
                    int pt2 = 0;//指向check[i]
    
                    while(pt2 < check[t].len && pt1 < l)
                    {
                        if(check[t].s[pt2] == a[pt1])
                        {
                            pt1++;
                            pt2++;
                        }
                        else
                            pt1++;
                    }
    
                    if(pt2 == check[t].len)//表示完全匹配成功
                    {
                        dp[i] = min(dp[i], dp[pt1] + (pt1 - i) - pt2);
                    }
                }
            }
        }
    
        printf("%d
    ", dp[0]);
    
        return 0;
    }
  • 相关阅读:
    2018 徐州网络赛A
    2018 徐州网络赛 G
    Split The Tree(dfs序+树状数组)
    A Question of Ingestion(Dp)
    Starting a Scenic Railroad Service(前缀和+差分)
    Rendezvous on a Tetrahedron (模拟)
    7032: Knightsbridge Rises(网络流+dfs)
    7033: Lounge Lizards(lis)
    并发服务器
    fork和exec函数
  • 原文地址:https://www.cnblogs.com/dishu/p/4293369.html
Copyright © 2011-2022 走看看