zoukankan      html  css  js  c++  java
  • UPC3459: 移除字符

    题目描述

    给出一个字符串 s 和一些长度为 3 的非法串(由英文小写字母组成)。你需要在字符串 s 中移除一些字符使得变更后的字符串不包含任何非法串。

    求最小的需要移除的字符个数。

     

    输入

    输入含多组数据,一直处理到文件结束。对于每组数据:
        第一行是字符串 s,长度不大于 50000。
        第二行是非法串个数,个数不大于 676。
        第三行到最后一行每行 3 个字母表示非法串。

     

    输出

    对每组数据,输出最小需要移除的字符个数。

     

    样例输入

    abcdd
    2
    abc
    abd
    

    样例输出

    1
    

     

    来源/分类

     2017 华东理工上海高校邀请赛  

    #include "bits/stdc++.h"
    
    using namespace std;
    
    const int maxn = 5e4 + 100;
    bool illegal[27 * 26 * 26 + 30];
    int dp[maxn][26 * 26 + 30];//de了一个小时的bug。。 这里第二维一开始开了27*26,下面为to是26*26+26,访问错误地址
    char str[maxn];
    
    int main() {
        freopen("input.txt", "r", stdin);
        int m, n;
        while (scanf("%s%d", str + 1, &m) != EOF) {
            n = strlen(str + 1);
            char s[5];
            memset(illegal, false, sizeof(illegal));
            illegal[0] = true;//
            for (int i = 0; i < m; i++) {
                scanf("%s", s);
                int val = 0;
                for (int j = 0; j < 3; j++) {
                    val = val * 26 + s[j] - 'a' + 1;
                    illegal[val] = true;//记录不合法子串的前缀
                }
            }
            memset(dp[0], 0x80, sizeof dp[0]);//负无穷
            dp[0][0] = 0;
            const int to = 26 * 26 + 26;
            //dp[i][j]表示到i时以 不合法子串前缀j 为后缀的合法串的最大长度
            for (int i = 0; i <= n; i++) {
                memmove(dp[i + 1], dp[i], sizeof(dp[i]));
                int x = str[i + 1] - 'a' + 1;
                for (int j = 0; j <= to; j++) {//插入一个字符后跟所有的最长串匹配,转移时控制不要包含非法串
                    if (!illegal[j] || dp[i][j] < 0) continue;//如果j是合法子串,则不需要转移
                    if (j <= 26) {
                        int k = j * 26 + x;//把x接在j后面得到k
                        if (!illegal[k]) k = x;
                        if (!illegal[k]) k = 0;
                        dp[i + 1][k] = max(dp[i + 1][k], dp[i][j] + 1);
                    } else if (!illegal[j * 26 + x]) {
                        int k = (j % 26 + (j % 26 == 0) * 26) * 26 + x;//把x接在j的最后一个字母后面得到k
                        if (!illegal[k]) k = x;
                        if (!illegal[k]) k = 0;
                        dp[i + 1][k] = max(dp[i + 1][k], dp[i][j] + 1);
                    }
                }
            }
            int ans = 0;
            for (int i = 0; i <= to; i++) {
                ans = max(ans, dp[n][i]);
            }
            printf("%d
    ", n - ans);
        }
        return 0;
    }
  • 相关阅读:
    HDU 2196 Computer (树形DP)
    HDU 4756 Install Air Conditioning (MST+树形DP)
    HDU 4126 Genghis Khan the Conqueror (树形DP+MST)
    HDU 4714 Tree2cycle (树形DP)
    HDU 1159 Common Subsequence (LCS)
    HDU 2159 FATE (二维背包)
    HDU 2602 Bone Collector (01背包DP)
    HDU 5918 Sequence I (KMP)
    关于一些逗逼函数//atoi,itoa,strtok,strupr,
    二叉树—-1(No.9HN省赛小题)
  • 原文地址:https://www.cnblogs.com/albert-biu/p/10344299.html
Copyright © 2011-2022 走看看