当找不到导致错误答案的输入案例时,有什么方法可以调试Online Judge问题?

问题描述 投票:0回答:1

现在,我正在尝试解决UVa问题843:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=784

这是我尝试过的C ++代码。

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <set>

void decode(int start, std::string& match);
bool canMatch(std::string& match, std::string w, std::string d);
bool hasConflict(std::string match);

int N;
std::vector<std::string> dict;      // Dictionary for allowed words
std::vector<std::string> words;     // List of words that is in a line for decrypting
std::set<std::string> exist;        // Set of `dict` for faster searching
std::set<std::string>::iterator it; // Iterator for the set
std::string temp;                   // Temp buffer for string
std::string cyphertext;             // Input line (encrypted)
bool done = false;                  // Flag for done decrypting

int main(){
    // Building dictionary, set used to find word faster
    std::cin >> N;
    for(int i = 0;i < N;++i){
        std::cin >> temp;
        if((it = exist.find(temp)) == exist.end()){
            dict.push_back(temp);
            exist.insert(temp);
        }
    }

    // Decrept each line
    scanf("%*c");
    while(getline(std::cin, cyphertext)){
        // For empty lines
        if(!cyphertext.length()){
            continue;
        }

        // Initialize
        std::string match(26, '*');
        done = false;

        // Parse the words in line into vector.
        words.clear();
        std::istringstream iss(cyphertext);
        while(iss >> temp){
            words.push_back(temp);
        }

        decode(0, match);

        // Debug
        // std::cout << "Result: ============================\n";
        // std::cout << "The matching is:\n";
        // std::cout << "abcdefghijklmnopqrstuvwxyz\n";
        // std::cout << match << "\n";


        // Restore
        //std::cout << cyphertext << "\n";
        if(!done){
            match.assign(26, '*');
        }
        temp = "";
        for(int i = 0;i < cyphertext.length();++i){
            if(cyphertext[i] == ' '){
                temp += ' ';
            }
            else{
                temp += match[cyphertext[i] - 'a'];
            }
        }

        std::cout << temp << "\n"; 
    }

    return 0;
}

// Backtracking for decoding
void decode(int start, std::string& match){
    // Search from the first word
    std::string backupCypher = match;
    for(int i = 0;i < dict.size();++i){
        // std::cout << "Trying to decode word \"" << words[start] << "\"\n";
        match = backupCypher;
        if(dict[i].length() == words[start].length()){
            if(canMatch(match, words[start], dict[i])){
                if(start == words.size() - 1){
                    // std::cout << "End of sentence reached.\n";
                    // std::cout << "Current match:\n";
                    // std::cout << "abcdefghijklmnopqrstuvwxyz\n";
                    // std::cout << match << "\n\n\n";
                    done = true;
                }
                else{
                    // std::cout << "Advancing to next word.\n";
                    // std::cout << "Current match:\n";
                    // std::cout << "abcdefghijklmnopqrstuvwxyz\n";
                    // std::cout << match << "\n\n\n";
                    decode(start + 1, match);
                    if(done){
                        break;
                    }
                    match = backupCypher;
                }
            }
        }
        // Check if is done
        if(done){
            break;
        }
    }
    return;
}

// Try matching the word d with the encrypted word w
bool canMatch(std::string& match, std::string w, std::string d){
    for(int i = 0;i < w.length();++i){
        if(match[w[i] - 'a'] == '*' || match[w[i] - 'a'] == d[i]){
            match[w[i] - 'a'] = d[i];
        }
        else{
            // std::cout << "Matching " << w[i] << " to " << d[i] << " Failed!\n";
            return false;
        }
    }
    if(hasConflict(match)){
        // std::cout << "Has conflict!\n";
        // std::cout << "abcdefghijklmnopqrstuvwxyz\n";
        // std::cout << match << "\n";
        return false;
    }
    return true;
}

bool hasConflict(std::string match){
    bool used[26] = {false};
    std::sort(match.begin(), match.end());

    for(auto iter = match.begin();iter != match.end();++iter){
        if(used[*iter - 'a']){
            return true;
        }
        used[*iter - 'a'] = true;
    }
    return false;
}

得到错误答案。阅读文章如何调试我的代码之后,我尝试了各种suDebug输入和自写输入,用推荐的std::cout打印变量的值,并通过在uDebug站点上进行测试来构建以下随机输入生成器,它总是告诉我我所有的输出都是正确的。我想知道是否还有其他方法可以调试当我找不到导致错误的输入大小写时

顺便说一句,这是我写的输入生成器:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>

int main(){
    char carr[] = {'a', 'b', 'c', 'd', 'e',
                   'f', 'g', 'h', 'i', 'j', 
                   'k', 'l', 'm', 'n', 'o', 
                   'p', 'q', 'r', 's', 't', 
                   'u', 'v', 'w', 'x', 'y', 'z'};
    int randNum;

    srand(time(NULL));
    std::cout << (randNum = rand() % 1000 + 1) << "\n";
    for(int i = 0;i < randNum;++i){
        int len = rand() % 16 + 1;
        std::string temp = "";
        for(int j = 0;j < len;++j){
            temp += carr[rand() % 26];
        }
        std::cout << temp << "\n";
    }

    for(int i = 0;i < 100;++i){
        std::string temp = "";
        int count = 0;
        do{
            ++count;
            int len = rand() % 16 + 1;
            for(int j = 0;j < len;++j){
                temp += carr[rand() % 26];
            }
            temp += " ";
        }while(rand() % 3 != 0 && count < 10);
        temp.pop_back();
        std::cout << temp << std::endl;
    }

    return 0;
}

非常感谢您的帮助。


一些输入和输出:(首先是问题给出的,第二是自写的。)

Input:
6
and
dick
jane
puff
spot
yertle
bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd
Output:
dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ****** 
Input:
3
a
aa
aaa
z
zz
zzz
xx
cc
zzz xx c
zzz zz z
zzz xx zz z
(Empty Line)
xx
Output:
a
aa
aaa
aa
aa
*** ** *
aaa aa a
*** ** ** *
aa
c++ debugging
1个回答
5
投票

打开-fsanitize=undefined,我在hasConflict中收到关于索引超出范围的警告。

实际上,似乎hasConflict有时会传递包含*的字符串,在这种情况下,used[*iter - 'a']bool used[26]的范围之外。

不确定这是否是导致您失败的错误,但肯定是a错误。

© www.soinside.com 2019 - 2024. All rights reserved.