使用 DP 的缩写问题中的错误答案
Wrong answer in Abbreviations problem using DP
有人可以解释我的代码有什么问题吗?我在 7 个测试用例中收到“Abort called”。其余成功。
我有一个二维 dp 数组,其大小为:n+1 x m+1 其中 n 和 m 分别是 a 和 b 的大小。因此,行代表字符串 a,列代表字符串 b。
首先,我将 dp[0][0] 设置为 1,因为可以将空字符串变成空字符串。
所以,最初,我正在检查是否可以将 a 的任何子字符串转换为空字符串(在第一个 for 循环中)。对于没有任何大写字母的 a 的所有子字符串都是如此。只要有一个大写字母,其余的子串就不能转换了。
然后(在下一个双 for 循环中),我正在检查所有情况。
情况 1:a[i-1] == b[i-1] -> 如果两个字母完全相同,则 dp[i][j ] = dp[i-1][j-1]
案例 2:a[i-1] 是小写(这有 2 个子案例):
情况 2.1: a[i-1] 和 b[j-1] 是相同的字母(但不是相同的大小写)-> 那么我们可以改变 a [i-1] 或删除它。所以:
dp[i][j] = dp[i-1][j-1] || dp[i-1][j].
情况2.2:a[i-1]和b[j-1]不相同->在这种情况下,我们只能删除a[i-1],因为它较低案件 。所以:dp[i][j] =
dp[i-1][j]
P.S。程序的主要逻辑就在abbreviation()函数里面。
代码(已编辑):
#include <bits/stdc++.h>
using namespace std;
bool isSame(const char &a, const char &b)
{
return a == b || abs(a - b) == 32;
}
bool isLower(const char &a)
{
return a > 90 && a < 123;
}
// Complete the abbreviation function below.
string abbreviation(const string &a, const string &b)
{
int n = a.size(), m = b.size();
if (m > n)
return "NO";
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; ++i)
{
if (isLower(a[i - 1]) && dp[i - 1][0])
dp[i][0] = 1;
}
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= i; ++j)
{
if (a[i - 1] == b[j - 1])
dp[i][j] = dp[i - 1][j - 1];
if (isLower(a[i - 1]))
{
if (isSame(a[i - 1], b[j - 1]))
dp[i][j] = dp[i - 1][j - 1] || dp[i - 1][j];
else if (dp[i - 1][j])
{
dp[i][j] = dp[i - 1][j];
}
}
}
}
return dp[n][m] ? "YES" : "NO";
}
int main()
{
int t;
cin >> t;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
while (t--)
{
string a, b;
getline(cin, a);
getline(cin, b);
cout << abbreviation(a, b) << "\n";
}
return 0;
}
代码中的错误是“分段错误”。
因为下面的循环:
for (int j = 1; j <= i; ++j)
因为循环迭代直到 i(它可能大于 m,即 b 的大小)。这就是 分段错误 的原因。
现在下面的代码通过了所有的测试用例。
#include <bits/stdc++.h>
using namespace std;
bool isSame(const char&a, const char&b){
return a==b || abs(a-b)==32;
}
bool isLower(const char&a){
return a >90 && a<123;
}
// Complete the abbreviation function below.
string abbreviation(string a, string b) {
int n = a.size(), m = b.size();
if(m>n)
return "NO";
int dp[n+1][m+1] = {};
dp[0][0] = 1;
for(int i=1; i<=n; ++i)
if(isLower(a[i-1]) && dp[i-1][0])
dp[i][0] = 1;
for(int i=1; i<=n; ++i)
for(int j =1; j<=min(i,m); ++j){
if(a[i-1]==b[j-1])
dp[i][j] = dp[i-1][j-1];
if(isLower(a[i-1]))
{
if(isSame(a[i-1], b[j-1]))
dp[i][j] = dp[i-1][j-1] || dp[i-1][j];
else if(dp[i-1][j])
dp[i][j] = dp[i-1][j];
}
}
return dp[n][m] ? "YES" : "NO";
}
int main()
{
int q;
cin >> q;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
for (int q_itr = 0; q_itr < q; q_itr++) {
string a;
getline(cin, a);
string b;
getline(cin, b);
string result = abbreviation(a, b);
cout << result << "\n";
}
return 0;
}
有人可以解释我的代码有什么问题吗?我在 7 个测试用例中收到“Abort called”。其余成功。
我有一个二维 dp 数组,其大小为:n+1 x m+1 其中 n 和 m 分别是 a 和 b 的大小。因此,行代表字符串 a,列代表字符串 b。
首先,我将 dp[0][0] 设置为 1,因为可以将空字符串变成空字符串。
所以,最初,我正在检查是否可以将 a 的任何子字符串转换为空字符串(在第一个 for 循环中)。对于没有任何大写字母的 a 的所有子字符串都是如此。只要有一个大写字母,其余的子串就不能转换了。
然后(在下一个双 for 循环中),我正在检查所有情况。
情况 1:a[i-1] == b[i-1] -> 如果两个字母完全相同,则 dp[i][j ] = dp[i-1][j-1]
案例 2:a[i-1] 是小写(这有 2 个子案例):
情况 2.1: a[i-1] 和 b[j-1] 是相同的字母(但不是相同的大小写)-> 那么我们可以改变 a [i-1] 或删除它。所以:
dp[i][j] = dp[i-1][j-1] || dp[i-1][j].
情况2.2:a[i-1]和b[j-1]不相同->在这种情况下,我们只能删除a[i-1],因为它较低案件 。所以:dp[i][j] =
dp[i-1][j]
P.S。程序的主要逻辑就在abbreviation()函数里面。
代码(已编辑):
#include <bits/stdc++.h>
using namespace std;
bool isSame(const char &a, const char &b)
{
return a == b || abs(a - b) == 32;
}
bool isLower(const char &a)
{
return a > 90 && a < 123;
}
// Complete the abbreviation function below.
string abbreviation(const string &a, const string &b)
{
int n = a.size(), m = b.size();
if (m > n)
return "NO";
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; ++i)
{
if (isLower(a[i - 1]) && dp[i - 1][0])
dp[i][0] = 1;
}
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= i; ++j)
{
if (a[i - 1] == b[j - 1])
dp[i][j] = dp[i - 1][j - 1];
if (isLower(a[i - 1]))
{
if (isSame(a[i - 1], b[j - 1]))
dp[i][j] = dp[i - 1][j - 1] || dp[i - 1][j];
else if (dp[i - 1][j])
{
dp[i][j] = dp[i - 1][j];
}
}
}
}
return dp[n][m] ? "YES" : "NO";
}
int main()
{
int t;
cin >> t;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
while (t--)
{
string a, b;
getline(cin, a);
getline(cin, b);
cout << abbreviation(a, b) << "\n";
}
return 0;
}
代码中的错误是“分段错误”。
因为下面的循环:
for (int j = 1; j <= i; ++j)
因为循环迭代直到 i(它可能大于 m,即 b 的大小)。这就是 分段错误 的原因。
现在下面的代码通过了所有的测试用例。
#include <bits/stdc++.h>
using namespace std;
bool isSame(const char&a, const char&b){
return a==b || abs(a-b)==32;
}
bool isLower(const char&a){
return a >90 && a<123;
}
// Complete the abbreviation function below.
string abbreviation(string a, string b) {
int n = a.size(), m = b.size();
if(m>n)
return "NO";
int dp[n+1][m+1] = {};
dp[0][0] = 1;
for(int i=1; i<=n; ++i)
if(isLower(a[i-1]) && dp[i-1][0])
dp[i][0] = 1;
for(int i=1; i<=n; ++i)
for(int j =1; j<=min(i,m); ++j){
if(a[i-1]==b[j-1])
dp[i][j] = dp[i-1][j-1];
if(isLower(a[i-1]))
{
if(isSame(a[i-1], b[j-1]))
dp[i][j] = dp[i-1][j-1] || dp[i-1][j];
else if(dp[i-1][j])
dp[i][j] = dp[i-1][j];
}
}
return dp[n][m] ? "YES" : "NO";
}
int main()
{
int q;
cin >> q;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
for (int q_itr = 0; q_itr < q; q_itr++) {
string a;
getline(cin, a);
string b;
getline(cin, b);
string result = abbreviation(a, b);
cout << result << "\n";
}
return 0;
}