0

I am getting this above error and I am unable to debug the cause for it. Can anyone help me with this (what's causing this error)?

Problem Statement: Finding Longest Common Prefix

Source: https://leetcode.com/problems/longest-common-prefix/

Code(Using Divide and Conquer):

#include <iostream>
#include <unordered_map>
#include <string> 
#include <vector>

using namespace std;
class Solution {
public:
    string common_prefix(string left, string right){       
        int minim = min(left.length(), right.length());
        for (int i=0; i<minim; i++){
            if (left[i]!=right[i]){
                return left.substr(0, i);
            }
        }
        return "" ;
    }
    string dap(vector<string>& a, int l, int r){
        if (l==r) return a[l];    

        int mid = (l+r)/2;
        string left = dap(a, l, mid);
        string right = dap(a, mid+1, r);
        return common_prefix(left, right);
    }
    string longestCommonPrefix(vector<string>& strs) {

        
        return dap(strs, 0, strs.size());
        
    }
};


int main()
{
    Solution s;
    vector<string> st{"flower","flow","flight"};
    string ans = s.longestCommonPrefix(st);
    cout << ans;
}

Traceback:

Runtime Error
terminate called after throwing an instance of 'std::length_error'
  what():  basic_string::_M_create

Input:

["flower","flow","flight"]

Expected Output:

"fl"

link: https://ide.geeksforgeeks.org/9nKPmtFPd5

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
Pygirl
  • 12,969
  • 5
  • 30
  • 43
  • O.T.: `common_prefix(string left, string right)` will produce unnecessary copies of your strings. I would use `const std::string &` instead of `std::string` for the parameters. – Scheff's Cat May 20 '21 at 07:27
  • @AlanBirtles: I am using leet code compiler. Code was expecting in that format only. I don't know how to provide the solution in a general form. – Pygirl May 20 '21 at 07:29
  • 1
    I somehow expected this reply. Leet code provides internally a `main()` to make an instance of your `class Solution` and call it somehow (with a certain function). Just add this code and debug your application locally until you found out what's happening. That's the very usual way to go... ([What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/7478597)) – Scheff's Cat May 20 '21 at 07:32
  • 1
    You have access out of bounds in `if (l==r) return a[l];` when `l` and `r` are 3 for 3 items input vector. In sequence of calling `dap` there is an invocation `dap(3,3)` .. – rafix07 May 20 '21 at 07:36
  • 2
    @Pygirl *and I am unable to debug the cause for it* -- Why are you unable to debug the code? Get a real C++ compiler, compile the code locally, add a `main()` with data. – PaulMcKenzie May 20 '21 at 07:38
  • @Pygirl [See this](http://coliru.stacked-crooked.com/a/8bc068fab9a26997). A [mcve], ready to be debugged using a debugger. – PaulMcKenzie May 20 '21 at 07:45
  • @Scheff: I tried to debug but I am getting `Abort signal from abort(3) (SIGABRT)` error. – Pygirl May 20 '21 at 08:04
  • @AlanBirtles: I addedinput and expected output. – Pygirl May 20 '21 at 08:06
  • _I am getting Abort signal from abort(3) (SIGABRT)_ This is actually a lucky case. If you run it in a debugger then it will stop in `abort()`. (This is a lib. function call which will exit your application after the crash.) However, when it stopped in `abort()`, you can "walk up" the call stack and have a look what called what with which arguments and what was in the local variables just before this crash occurred. With a bit more luck you will find out what went wrong. – Scheff's Cat May 20 '21 at 08:28
  • @Scheff Oh I see. Thanks for the info. I ain't good with c++. I am trying to debug the code using `codeblock` (using linux) I get the error:. `Terminated due to `logic_error``. If you can share some useful resources on how to do do the debugging like in python we have `pdb` . I ain't able to find out the way to get the line causing this issue. I can see `if (l==r)` is causing the problem by setting the `a[l]` to `a[l-1]` – Pygirl May 20 '21 at 08:34
  • 1
    On Linux (and if enabled), an aborted application will produce a so-called core dump. With `gdb`, the application and the core dump can be loaded to see the call stack as it was before the call of `abort()`. So, no new run in debugger is needed. However, if it's a reproducible error then just re-running the application in the debugger will work as well. – Scheff's Cat May 20 '21 at 08:34
  • 1
    THE Linux debugger is `gdb`. It's very powerful and native used in the console. However, a lot of IDEs wrapped it in their GUI. (No idea, how good or bad it works - no experience.) So, to get a general idea, just google for gdb. Then you may find the resp. buttons of the gdb commands in CodeBlocks (your IDE) and realize how it can be used more conveniently from there. – Scheff's Cat May 20 '21 at 08:36
  • @Scheff: Thanks I will look into that :) Thankseveryone for the help got to learn basic and important stuffs. – Pygirl May 20 '21 at 08:40
  • 1
    Just wondering: Why don't you use a simple double loop?`if(strs.empty()) { return std::string(); } for(size_t i = 0, max = strs[0].length(); i < max; ++i) { for(size_t j = 1; j < strs.size(); ++j) { if(strs[j][i] != strs[0][i]) { return strs[0].substr(0, i); } } } return strs[0];` – Aconcagua May 25 '21 at 06:02
  • 1
    Not fully sure if leetcode is very best site for learning (good) C++. They apparently impose [`using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) on you and the vector should have been accepted as `const` reference. At very least they should have written that in some remarks, only allowing to modify the vector to make it easier for you. – Aconcagua May 25 '21 at 06:06

2 Answers2

1

You have two issues in your code.

  1. your initial value for r is strs.size(), after a few recursions you get to the line if (l == r) return a[l]; with r still at its initial value. a[a.size()] leads to undefined behaviour. The initial value for r should be strs.size() - 1.

  2. In common_prefix if the whole of the shorter string is the prefix of the longer one you return an empty string. You should return left.substr(0, minim) instead.

For efficiency you should use const string& left instead of string left in your function parameters to avoid copying the strings. You could also use std::string_view to avoid copying strings at all:

#include <iostream>
#include <string> 
#include <vector>
#include <string_view>

class Solution {
public:
    std::string_view common_prefix(const std::string_view& left, const std::string_view& right) {
        int minim = std::min(left.length(), right.length());
        for (int i = 0; i < minim; i++) {
            if (left[i] != right[i]) {
                return left.substr(0, i);
            }
        }
        return left.substr(0, minim);
    }

    std::string_view dap(const std::vector<std::string>& a, int l, int r) {
        if (l == r) return a[l];

        int mid = (l + r) / 2;
        std::string_view left = dap(a, l, mid);
        std::string_view right = dap(a, mid + 1, r);
        return common_prefix(left, right);
    }

    std::string_view longestCommonPrefix(const std::vector<std::string>& strs) {
        return dap(strs, 0, strs.size()-1);
    }
};


int main()
{
    Solution s;
    std::vector<std::string> st{ "flower","flow","flight" };
    std::string_view ans = s.longestCommonPrefix(st);
    std::cout << ans;
}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • Got it. The logical issues in the code. Thanks for providing the second point also. I will from now onward will take care of it. – Pygirl May 20 '21 at 08:38
0

std::length_error means you are trying to create a string longer than std::string::max_size()

Therefore you need to track the string that throws via. try/catch

HerrNilsen
  • 43
  • 1
  • 8
  • I know the error but what causing this error. This is where I am stuck. – Pygirl May 20 '21 at 07:30
  • 4
    @Pygirl string lengths are actually handled with `size_t` which is an `unsigned` type of pointer size. Using `int` is dangerous. If the `int` becomes (accidentally) negative this may result in huge unsigned numbers. These "huge unsigned numbers" are usually too big to be used for an allocation. So, looking for suspicious `int` values is the task... – Scheff's Cat May 20 '21 at 07:35