Abbreviation ---- hackerrank

---恢复内容开始---

https://www.hackerrank.com/contests/world-codesprint-6/challenges/abbr

给定两个串str和sub。

对于每个str中的小写字母,可以变成大写,其他小写字母,能无条件删除,问其能否变成sub

一开始的时候贪心,用个数组标记两个串中字母各有多少个,一直模拟。然后卡死在一组数据上。我也发现不了是什么数据。

那么就dp吧

考虑dp[i][j]表示在str中的第i位转变成sub中的第j位,是否可能。

dp[i][j] = 1表示可能。

那么,如果dp[i - 1][j - 1] = 1;  就是前面的已经转换完成。

对于第i个字符。str[i]。如果是小写,那么dp[i][j - 1] = 1是必然的。因为我可以无条件删除小写字母,就是因为本来的i - 1位和j - 1位是可以搭配的了,现在说第i位和第j - 1位也可以搭配,因为删除第i位就可以了,

同时,如果把str[i]转成大写字母,和sub[j]相等的话,就说明,dp[i][j] = 1;说明本位可以搭配。

否则,如果str[i]是大写字母,就只能看看是不是和sub[j]一样了。一样就dp[i][j] = 1;

最后只要看看dp[lenstr][lensub]是否等于1即可。就是最后末尾是否能转换成功。

注意的是,对于小写字母,它是可以无条件删除的,所以可能是dp[i][j - 1] = dp[lenstr][lensub]

所以枚举j要到lensub + 1  这样才能把状态一直传递下去

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1000 + 20;
bool dp[maxn][maxn];
char str[maxn];
char sub[maxn];
//void work () {
//    memset (dp, 0, sizeof dp);
//    scanf ("%s%s", str + 1, sub + 1);
//    int lenstr = strlen (str + 1);
//    int lensub = strlen (sub + 1);
//    dp[1][1] = 1;
//    for (int i = 1; i <= lenstr; ++i) {
//        for (int j = 1; j <= lensub + 1; ++j) {
//            if (dp[i][j]) {
//                if (str[i] >= 'a' && str[i] <= 'z') {
//                    dp[i + 1][j] = 1;
//                    if (str[i] - 32 == sub[j]) {
//                        dp[i + 1][j + 1] = 1;
//                    }
//                } else {
//                    if (str[i] == sub[j]) {
//                        dp[i + 1][j + 1] = 1;
//                    }
//                }
//            }
//        }
//    }
//    if (dp[lenstr + 1][lensub + 1]) {
//        printf ("YES
");
//    } else {
//        printf ("NO
");
//    }
//}
void work () {
    memset (dp, 0, sizeof dp);
    scanf ("%s%s", str + 1, sub + 1);
    int lenstr = strlen (str + 1);
    int lensub = strlen (sub + 1);
    dp[0][0] = 1;
    for (int i = 1; i <= lenstr; ++i) {
        dp[i][0] = 1;
    }
    for (int i = 1; i <= lenstr; ++i) {
        for (int j = 1; j <= lensub + 1; ++j) {
            if (dp[i - 1][j - 1]) {
                if (str[i] >= 'a' && str[i] <= 'z') {
                    dp[i][j - 1] = 1;
                    if (str[i] - 32 == sub[j]) {
                        dp[i][j] = 1;
                    }
                    if (str[i] == sub[j]) {
                        dp[i][j] = 1;
                    }
                } else {
                    if (str[i] == sub[j]) {
                        dp[i][j] = 1;
                    }
                }
            }
        }
    }
//    printf ("%d
", dp[5][3]);
    if (dp[lenstr][lensub]) {
        printf ("YES
");
    } else {
        printf ("NO
");
    }
}
int main () {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    scanf ("%d", &t);
    while (t--) work ();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5837800.html