最接近的字符串:查找字符串数组中两个字符串之间的最小距离

时间:2019-08-02 04:07:32

标签: c++ algorithm

您将得到一个字符串数组,后跟两个单词。您必须在给定的字符串数组中找到两个单词之间的最小距离

例如: (“ the”,“ quick”,“ brown”,“ fox”,“ quick”) 距离(“ fox”,“ the”)= 3 distance(“ quick”,“ fox”)= 1

为什么此代码在下面给出的测试用例中失败?

#include<iostream>
#include<string>
#include<bits/stdc++.h>

using namespace std;

int search(vector<string>v,string s1)
{
    for(int i=0;i<v.size();i++)
    {
        if(v[i]==s1)
        {
            return i;
        }
    }
    return -1;
}

int main() 
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin >> n;
        vector<string> v;
        for(int i = 0; i < n; ++i)
        {
            string a;
            cin >> a;
            v.push_back(a);

        }
        string s1;
        cin >> s1;
        string s2;
        cin >> s2;
        int p, y;
        p = search(v, s1);
        y = search(v, s2);
        int d = abs(p-y);
        cout<<d<<endl;
    }
    return 0;
}

答案错误。 !!!错误的答案 您的代码可能不适用于多个测试用例(TC)。 您的代码失败的第一个测试用例:

输入: 52 rbkiruxixlqpjkbcdctwvsogiurmicjafuiwrhhqsyiflkjqodomwfvhanvirgjydtyudgnyhweujpmxtdmsiickxyvrffri rbkiruxixlqpjkbcdctwvsogiurmicjafuiwrhhqsyiflkjqodomwfvhanvirgjydtyudgnyhweujpmxtdmsiickxyvrffri ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ffyvehskceaqevtqqectpasluasmkvdpbelhlgtqkw ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimiki ambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtqrckknhuefborlyaoo ueimikiambnhdivnfbfigtq rckknhuefborlyaoo xgnuvsvdbcwtwahjpogvthlnvmpkbsocbcwwwubyxauwccgrtpqpw xgnuvsvdbcwtwahjpogvthlnvmpkbsocbcwwwubyxauwccgrtpqpw xgnuvsvdbcwtwahjpogvthlnvmpkbsocbcwwwubyxauwccgrtpqpw xgnuvsvdbcwtwahjpogvthlnvmpkbsocbcwwwubyxauwccgrtpqpw xgnuvsvdbcwtwahjpogvthlnvmpkbsocbcwwwubyxauwccgrtpqpw sqtfupuwqwvqwqtvqtqpytysnojdln ueimikiambnhdivnfbfigtqrckknhuefborlyaoo rbkiruxixlqpjkbcdctwvsogiurmicjafuiwrhhsyylklkjqodomwfvhanvirgjydtyudgnyhweujpmxtdmsiickxyvrffri

其正确的输出是: 11

您的代码的输出为: 12

4 个答案:

答案 0 :(得分:1)

您的代码未处理输入数组中的重复字符串。

例如,如果输入数组为["ghi", "abc", "abc", "abc", "ghi", "def", "ghi", "def"] 然后,“ abc”和“ def”之间的最小距离应为:2(在索引35之间),但是您的代码将输出:4

答案 1 :(得分:0)

以下修改后的代码突出显示了三个问题:

int search(const vector<string>&v, const string& s1)  // use pass by const reference for performance here
{
    for (int i = 0; i < v.size(); i++)
    {
        if (v[i].compare(s1) == 0) // use std::string::compare to compare two strings 
        {
            return i;
        }
    }
    return -1;
}


int main{
    /* other codes */
    p = search(v, s1);
    y = search(v, s2);
    if (p != -1 && y != -1) { // display output only when both searches are successful
        int d = abs(p - y);
        cout << d << endl;
    }
}

已编辑: 使用c ++ 11可以像这样简化:

int main() {
    string line;
    getline(cin, line);
    stringstream sstream{line};
    string word;
    vector<string> words;
    while (getline(sstream, word, ' ')) {
        words.push_back(word);
    }

    string from_string ="fox", to_string = "lamb";

    auto fromPos = std::distance(words.begin(), std::find(words.begin(), words.end(), from_string));
    auto toPos = std::distance(words.begin(), std::find(words.begin(), words.end(), to_string));

    if (fromPos != words.size() && toPos != words.size()) {
        cout << abs(fromPos - toPos) << endl;
    }
}

答案 2 :(得分:0)

代码失败,因为您有逻辑上的错误假设。

如果查看给定的测试字符串,您会发现有很多很长的字符串(带有许多字符)。这应该掩盖了测试集中只有5个不同字符串的事实。

如果将长字符串替换为非常短的字符串(例如S和索引计数),则输入将如下所示:

"S1", "S1", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S3",
"S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3",
"S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3",
"S3", "S3", "S3", "S3", "S3", "S3", "S3", "S4", "S4", "S4", "S4", "S4", "S5"

在逻辑上与原始版本完全相同,但会使阅读和理解变得更加困难。

使用测试用例的新表示形式,您将立即发现问题。此列表中有许多重复。而且,如果您将S1和S2作为搜索词,那么您将在代码中找到位置0处的第一个S1和位置2处的第一个S1。您将计算出距离2。错误。

因此,您可以假设始终搜索字符串的最后一次出现会很好,但这显然也行不通。我们将比较最后一个S1和最后一个S2。也错了。因此,我们需要将最后找到的searchWord1与第一个找到的searchWord2进行比较。

但这也行不通,可能会以错误的顺序给出搜索字符串。

而且,向量中其他位置可能会有更多的S1 S2序列。我们需要全部检查。

所有这些都会导致非常复杂的逻辑,因此我采用蛮力方法,将所有内容与所有内容进行比较。因此,如果找到一个S1,则将其与所有S2进行比较。我将对所有S1都这样做。

请参见下面的功能,该功能显示了我的工作。请注意。这只是众多可能性中的一种。请检查:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdint>

const std::vector<std::string> testStringVector{
"S1", "S1", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S2", "S3",
"S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3",
"S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3", "S3",
"S3", "S3", "S3", "S3", "S3", "S3", "S3", "S4", "S4", "S4", "S4", "S4", "S5"
};

const std::string searchWord1{ "S3" };
const std::string searchWord2{ "S1" };

size_t minDistance(const std::vector<std::string>& stringVector, const std::string& s1, const std::string& s2)
{
    unsigned int result = UINT_MAX;
    // Compare everything with everything else
    for (size_t i = 0; i < stringVector.size(); ++i) {
        // Find the string s1
        if (stringVector[i] == s1) {
            for (size_t k = 0; k < stringVector.size(); ++k) {
                // Do not compare to itself
                if ((i != k) && (stringVector[k] == s2)) {
                    unsigned int distance = std::abs(static_cast<int>(i) - static_cast<int>(k));
                    if (distance < result)
                        result = distance;
                }
            }
        }
    }
    return result;
}

int main()
{
    std::cout << "\nMin Distance for '" << searchWord1 << "' and '" << searchWord2 << " is: "
        << minDistance(testStringVector, searchWord1, searchWord2) << "\n";
    return 0;
}

答案 3 :(得分:0)

我希望我能很好地理解您的问题,如果可以,那么这也许就可以了(虽然我只是用简单的案例进行了测试,但不确定)。我在代码中添加了注释,而不是在此处进行解释。希望这不是问题。

#include <vector>
#include <string>
#include <limits>


class MinimalDistance
{
private:
    const std::vector<std::string> words;
    struct indexed_word
    {
        unsigned int index;
        std::string word;

        indexed_word() {}
        indexed_word(unsigned int index, const std::string& word) : index(index), word(word) {}

        bool operator<(const indexed_word& iw) const
        { return this->index < iw.index; }
        bool operator>(const indexed_word& iw) const
        { return this->index > iw.index; }
        bool operator==(const indexed_word& iw) const
        { return this->index == iw.index; }
        bool operator<=(const indexed_word& iw) const
        { return this->index <= iw.index; }
        bool operator>=(const indexed_word& iw) const
        { return this->index >= iw.index; }

        int operator-(const indexed_word& iw) const
        { return static_cast<int>(this->index) - static_cast<int>(iw.index); }

        bool operator==(const std::string& s) const
        { return this->word == s; }

        int operator=(const indexed_word& iw) const
        { return static_cast<int>(iw.index); }
    };

    // finds all occurrence of a word in the list
    // given on construction
    std::vector<indexed_word> find_all(const std::string& w)
    {
        // our indexed word list
        std::vector<indexed_word> iws;

        unsigned int i = 0;
        // iterate through every word in the class' vector
        for (const auto& word : words)
        {
            indexed_word iw(i, word);
            // if we find the word in the list
            // we put it in our indexed word list
            if (word == w)
            {
                iws.push_back(iw);
            }
            // increment the index
            i++;
        }

        return iws;
    }

    // helper function to find the minimal distance between an indexed word
    // and a list of indexed words
    // the indexed word vector contains the same words with different indexes
    int min_dist_in(const indexed_word& iw, std::vector<indexed_word>& iws)
    {
        int min = npos;

        // iterate through the given indexed word list
        for (const auto& iword : iws)
        {
            // if the distance is smaller
            // than the current min, change it
            if (std::abs(iw - iword) < min)
            {
                min = std::abs(iw - iword);
            }
        }

        return min;
    }

public:
    constexpr static int npos = std::numeric_limits<int>::max();

    MinimalDistance(const std::vector<std::string>& words) : words(words) {}
    int distance(const std::string& w1, const std::string& w2)
    {
        int min = npos;

        std::vector<indexed_word> iws1 = find_all(w1);
        std::vector<indexed_word> iws2 = find_all(w2);

        // if either of our vectors contain 0 elements,
        // return the 'not found min value'
        if (!(iws1.size() || iws2.size()))
            return min;

        // iterate through one of the word lists
        // the other will be the reference
        for (const auto& iw : iws1)
        {
            // finds a minimal distance between indexed words
            // in a given list
            const int n = this->min_dist_in(iw, iws2);
            // if this is smaller than the current minimum
            // change assign this value to it instead;
            if (n < min)
                min = n;
        }

        return min;
    }
};

int main()
{
    std::vector<std::string> words{ "the", "quick", "brown", "fox", "is", "coming", "quick", "to", "catch", "another", "quick", "fox" };

    MinimalDistance mindist(words);
    int dist = mindist.distance("quick", "fox");

    return 0;
}

我希望这会有所帮助。
它使用索引词列表来查找它们之间的最小距离(绝对值)。

修改:
另外,我不是C ++专家,所以建议不多! 干杯!