Function not declared in the scope (C++) - c++

I've been working on this Morris-Pratt algorithm to match substrings to a text, and I'm having trouble how to declare the failure function in the actual function so the compiler won't complain. I have like 2 hours to finish this. So please help me soon :/
int KMPmatch(const string& text, const string& pattern)
{
int n = text.size();
int m = pattern.size();
std::vector<int> fail = computeFailFunction(pattern);
int i = 0;
int j = 0;
while (i < n)
{
if (pattern[j] == text[i])
{
if (j == m-1) return i-m+1;
i++; j++;
}
else if (j > 0) j = fail[j-1];
else i++;
}
return -1;
}
//KMPFailure function
std::vector<int> computeFailFunction(const string& pattern)
{
std::vector <int> fail(pattern.size());
fail[0] = 0;
int m = pattern.size();
int j = 0;
int i = 1;
while (i < m)
{
if (pattern[j] == pattern[i])
{
fail[i] = j+1;
i++; j++;
}
else if (j > 0)
{
j = fail [j-1];
}
else
{
fail[i]= 0;
i++;
}
}
return fail;
}

Put std::vector<int> computeFailFunction(const string& pattern); ahead of int KMPmatch(const string& text, const string& pattern).
Or put function declaration into header file and included in source files, that is what project with multiple source files do.

Related

Longest palindrome in a string?

I want to print the longest palindrome in a string , I have written the code but this is giving wrong answer for some test cases . I am not able to find the error in my code .
Anyone help me with this , Anyhelp would be appreciated.
Input
vnrtysfrzrmzlygfv
Output
v
Expected output
rzr
Code:
class Solution {
public:
int ispalindrome(string s)
{
string rev = "";
int n = s.size();
for (int i = n - 1; i >= 0; i--) {
rev = rev + s[i];
}
if (rev == s) {
return 1;
}
return 0;
}
string longestPalin(string S)
{
// code here
int size = S.size();
int size_of_substr = 0;
string ans;
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
string s2 = S.substr(i, j);
if (ispalindrome(s2)) {
if (s2.size() > size_of_substr) {
ans = s2;
size_of_substr = s2.size();
}
else {
continue;
}
}
else {
continue;
}
}
}
return ans;
}
};
You are using substr(.) incorrectly. The second argument is the size of the substring.
string s2 = S.substr(i, j); should be replaced by string s2 = S.substr(i, j-i+1);
Moreover, this code will not be very efficient. To speed it up, I modified your code in the following way:
I pass the string by reference to the ispalindromefunction
I modified the algorithm to check if the substring is a palindrome. It returns false after the first mismatch
I don't build each substring explicitly. I only pass the start and beginning of the substring to the helper function
I start by checking if there exists a palindrome of the maximum size, and then I decrease its length. As soon as a palindrome is found, we know it has the maximum size, and we can stop the search
#include <iostream>
#include <string>
class Solution {
public:
int ispalindrome(const std::string& S, int i, int j) {
while (i < j) {
if (S[i++] != S[j--]) return 0;
}
return 1;
}
std::string longestPalindrome(const std::string& S) {
int size = S.size();
int imax = 1;
for (int size_of_substr = size; size_of_substr > 0; size_of_substr--, imax++) {
int j = size_of_substr - 1;
for (int i = 0; i < imax; i++, j++) {
if (ispalindrome(S, i, j)) {
std::string ans = S.substr(i, size_of_substr);
return ans;
}
}
}
return "";
}
};
int main() {
Solution sol;
std::string S;
std::cin >> S;
auto ans = sol.longestPalindrome(S);
std::cout << ans << "\n";
return 0;
}

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:25:17

I am solving the problem-->
Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.
and the error I get is Line 16: Char 17: runtime error: index 3 out of bounds for type 'int [n - 1]' (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:25:17
The line 16 is indice[i][j] = abs(i-j);
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
int n = nums.size();
int indice[n-1][n-1];
int total[n-1][n-1];
for(int i = 0;i<n;i++)
{
for(int j=0;j<n;j++)
{
indice[i][j]= abs(i-j);
total[i][j] = abs(nums[i]-nums[j]);
}
}
for(int i = 0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(indice[i][j]<=k && total[i][j]<=t)
{
return true;
}
}
}
return false;
}
};
for the test case [1,2,3,1] 3 0
The code works fine on my device and other compiler but not on leetcode's compiler.
Please help
This would fix your bug, however there is a problem with your algorithm, does not pass all the test cases:
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
int n = nums.size();
int indice[n][n];
int total[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
indice[i][j] = abs(i - j);
total[i][j] = abs(nums[i] - nums[j]);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (indice[i][j] <= k && total[i][j] <= t) {
return true;
}
}
}
return false;
}
};
This solution would pass using std::lower_bound:
// The following block might trivially improve the exec time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <vector>
#include <set>
#include <algorithm>
using ValueType = std::int_fast64_t;
static const struct Solution {
static const bool containsNearbyAlmostDuplicate(
const std::vector<int>& nums,
const int k,
const int t
) {
std::set<ValueType> window;
ValueType len = std::size(nums);
for (auto index = 0; index < len; ++index) {
if (index > k && index - k - 1 < len ) {
window.erase(nums[index - k - 1]);
}
const auto it = window.lower_bound((ValueType)nums[index] - t);
if (it != std::cend(window) && *it - nums[index] <= t) {
return true;
}
window.insert(nums[index]);
}
return false;
}
};

C++ "terminating with uncaught exception of type std::out_of_range: vector" error in a merge sort algorithm

I have a c++ code which should use merge sort algorithm to sort a file containing 800,000+ words each on a new line.
What I did ?
To start off, I tried implementing the following merge sort algorithm and tried testing it on a small piece of input. I cannot figure out where I am getting index out of bounds error with the vector. If anyone could help me with this, I would really appreciate
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
vector<string> merge(const vector<string>& first,
const vector<string>& second) {
// Write your code to merge vectors first and
// second onto result.
vector<string> output;
int i = 0;
int j = 0 ;
int size_first = sizeof(first);
int size_second = sizeof(second);
while(i < size_first || j < size_second){
if (i < size_first && j < size_second){
if (first.at(i) < second.at(j)){
output.push_back(first.at(i));
i++;
}
else{
output.push_back(second.at(i));
j++;
}
}
else if (i < size_first){
output.push_back(first.at(i));
i++;
}
else{
output.push_back(second.at(j));
j++;
}
}
return output;
}
void mergeSort(vector<string>& words) {
if (words.size() <= 1)
{
return;
}
int n = words.size();
int middle = n/2;
vector<string> first_half(middle);
for (int i = 0; i < middle; ++i) {
first_half[i] = words[i];
}
vector<string> second_half(n - middle);
for (int i = middle; i < n; ++i) {
second_half[i - middle] = words[i];
}
words = merge(first_half, second_half);
}
void sort(vector<string>& words) {
// Invoke mergeSort here.
mergeSort(words);
}
int main(){
vector<string> names;
names.push_back("Smith");
names.push_back("Abinash");
names.push_back("Ciara");
names.push_back("Reeta");
sort(names);
return 0;
}
std::vector has a size() member function that returns the number of elements in vector. sizeof(first) returns size in bytes of object representation of the type std::vector<string>, and that's not what you need.
int size_first = sizeof(first);
int size_second = sizeof(second);
Should be replaced with
int size_first = first.size();
int size_second = second.size();
You have a typo in:
else {
output.push_back(second.at(i));
j++;
}
Should be
...
output.push_back(second.at(j))
And another one. You forgot about the main thing - calling mergeSort for the parts before calling merge. Should be:
mergeSort(first_half);
mergeSort(second_half);
words = merge(first_half, second_half);
you are determining the size of the vector wrong:
int size_first = sizeof(first);
int size_second = sizeof(second);
replace it by
size_t size_first = first.size();
size_t size_second = second.size();

N queen using c++ and backtracking using a dynamic 2D array

I've been trying to solve the N queen problem using backtracking. Most of the approaches that I found online, involved vectors, making it difficult for me to visualize the solutions as some applets on the Internet do.
The solution I came up with, is giving me many problems(which i have a feeling are related to indexing of the dynamic 2D array used) and I'm not able to figure it out using Dev-C++ debugger.Any help and/or constructive criticism is highly appreciated. Many thanks in advance.
Here is the solution that i came up with:
#include<iostream>
#include<string.h>
#include<conio.h>
using namespace std;
void display(char** b, int len);
void initialize(char** &b, int k);
void consider1strow(char ** b, int len);
void markunsafe(char** board, int rowno, int colno);
void marksafe(char** board, int rowno, int colno);
void considerrow(char** board, int rowno);
void backtrack(char** board, int rowno);
bool checksafety(char** board, int rowno, int colno);
void place(char** board, int rowno, int colno);
void solve(char** board, int len);
int state[20] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
int len;
void display(char** board, int len)
{
int i, j;
cout << endl << "The current state of the board:" << endl;
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
cout << board[i][j];
}
cout << endl;
}
}
void initialize(char** &b, int k)
{
int i, j;
//create dynamic board
b = new char*[k];
for (i = 0; i < k; i++)
{
b[i] = new char[k];
}
//initialize array
for (i = 0; i < k; i++)
{
for (j = 0; j < k; j++)
{
b[i][j] = '-';
}
}
}
void consider1strow(char ** board, int len)
{
int col;
cout << "Enter the column to try for the first row!";
cin >> col;
board[0][col - 1] = 'Q';
state[0] = col - 1;
markunsafe(board, 0, col - 1);
display(board, len);
}
void markunsafe(char** board, int rowno, int colno)
{
int i, j;
//mark row as unsafe
for (i = 0; i < len; i++)
{
board[rowno][i] = 'x';
}
//mark column as unsafe
for (i = 0; i < len; i++)
{
board[i][colno] = 'x';
}
//mark unsafe diagonals
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
if ((rowno + colno) == (i + j))
{
board[i][j] = 'x'; //check if index gives a problem of +/- 1
}
if ((rowno - colno) == (i - j))
{
board[i][j] = 'x'; //check if index gives a problem of +/- 1
}
}
}
board[rowno][colno] = 'Q';
}
void marksafe(char** board, int rowno, int colno)
{
int i, j;
//mark row as safe
for (i = 0; i < len; i++)
{
board[rowno][i] = '-';
}
//mark column as unsafe
for (i = 0; i < len; i++)
{
board[i][colno] = '-';
}
//mark unsafe diagonals
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
if ((rowno + colno) == (i + j))
{
board[i][j] = '-'; //check if index gives a problem of +/- 1
}
if ((rowno - colno) == (i - j))
{
board[i][j] = '-'; //check if index gives a problem of +/- 1
}
}
}
}
void considerrow(char** board, int rowno)
{
bool safe = 0;
int i;
for (i = 0; i < len; i++)
{
safe = checksafety(board, rowno, i);
if (safe && (i >= state[rowno]))
{
break;
}
}
if (safe && (i >= state[rowno]))
{
place(board, rowno, i);
}
else if (!safe)
{
backtrack(board, rowno);
}
}
void backtrack(char** board, int rowno)
{
marksafe(board, rowno - 2, state[rowno - 2]);
considerrow(board, rowno);
}
bool checksafety(char** board, int rowno, int colno)
{
if (rowno == 0)
{
return 1;
}
else if (board[rowno][colno] == 'x')
{
return 0;
}
else if (board[rowno][colno] == '-')
{
return 1;
}
}
void place(char** board, int rowno, int colno)
{
board[rowno][colno] = 'Q';
state[rowno] = colno;
markunsafe(board, rowno, colno);
}
void solve(char** board, int len)
{
int i = 0;
if (i == len)
{
display(board, len);
}
else
{
consider1strow(board, len);
for (i = 1; i < len; i++)
{
considerrow(board, i);
}
}
}
int main()
{
char** board;
cout << "Enter the size of the board!";
cin >> len;
initialize(board, len);
solve(board, len);
getch();
}
It is running after the initial configuration, but you're not printing it. Change this (inside solve):
for(i=1;i<len;i++)
{considerrow(board,i);}
for this:
for(i=1; i<len; i++) {
considerrow(board,i);
display(board,len);
}
Besides that, there is a problem with the way you are doing backtracking. If no options are available, you are removing the queen from the previous row (that's ok) and then you are marking every cell it was attacking as safe (not ok). The problem is that some of these cells may be under attack by a different queen, so you cannot mark them as safe. Furthermore, you do not place a different queen on that row. I propose some solutions:
First, make it recursive: considerrow would call itself with the following row, and return true (1) if it succeeds or false (0) if it fails. If it fails with the next row, you can use the next queen in the current row and call considerrow again, until you succeed or run out of columns, in which case you return false.
To consider a different queen on a certain row, you can do two things: create a copy of the board which you would pass to considerrow for the next row (and thus keeping a 'before' copy to try a different queen), or mark every cell as safe, and then check all the existing queens to mark cells unsafe.
Edit:
To make it recursive, we are going to make considerrow call itself with the next value.
bool considerrow(char** board,int rowno) {
//Print the board
display(board,len);
bool safe=0;
int i;
for(i=0; i<len; i++) {
safe=checksafety(board,rowno,i);
if(safe) {
place(board,rowno,i);
//Is this the last row? If so, we suceeded
if (rowno==len-1) return 1;
//Call itself with next row, check if suceeded
if (considerrow(board,rowno+1))
return 1;
else //Failed, try a different row
backtrack(board,rowno);
}
}
return 0; //If we got here, then we ran out of colums. Return failure
}
The backtrack function can be modified to revert the current row like this:
void backtrack(char** board, int rowno) {
//Clear the current row
marksafe(board,rowno,state[rowno]);
//Check that every cell attacked by another queen is marked unsafe
for(int i=0; i<rowno; i++) markunsafe(board,i,state[i]);
}
Doing that, solve will only need to call the first row:
void solve(char** board,int len) {
considerrow(board,0);
display(board,len);
}

own implementation of std::string::find (brute-force search)

I am trying to find the occurrence of string T in string P and return the position of T in P.
This is what I have tried, but it is incorrect:
int bruteForce(string T, string P) {
int n, m;
for (int i = 0; i <= n-m; i++) {
int j = 0;
while (j < m && T[i+j] == P[j]) {
if (j == m) {
return i;
}
return 0;
}
}
}
What am I doing wrong? What am I missing?
In this part:
int n,m;
for (int i=0;i<= n-m;i++) {
you are using uninitialized local variable which results in undefined behavior. Also try to name your variables with something more meaningful than alphabet letters, I think what you actually meant was:
int bruteForce(std::string needle, std::string haystack) {
int needleLen = needle.length(),
haystackLen = haystack.length();
for (int i = 0; i <= needleLen - haystackLen; i++) {
int j = 0;
while (j < haystackLen && needle[i+j] == haystack[j]) {
if(j == haystackLen) {
return i;
}
return 0;
}
}
// return 0; <--
}
also note that in your function doesn't return any value in case when none of needle[i+j] equals haystack[j] (for every i). What about the situation when needle is "ab" and haystack is "aab" ~> while comparing needle[1] with haystack[1], your function would return 0 (it should be placed after for loop)
Another reasonable change would be changing passing by value to passing by reference to avoid copies being created. And since your function doesn't change these strings, its prototype should be:
int bruteForce(const std::string& needle, const std::string& haystack)
And in case you didn't want to intentionally create own implementation of std::string::find but yet for some reason you still need it to return 0 on failure (did you think about usage of your function when needle is equal to haystack?) it could look like this:
std::size_t bruteForce(const std::string& needle, const std::string& haystack) {
std::size_t pos = haystack.find(needle);
if (pos != std::string::npos)
return pos;
return 0;
}
...but if this is the case, you wouldn't call it bruteForce, would you? :)
I tried not to alter your code too much. My changes were:
Changed function parameters to const reference to avoid wasteful copies.
The variables n and m weren't initialized.
The inner while loop had problems. It didn't increment j and the test for success makes more sense outside the loop.
The return value for failure can't be 0 as that may be a valid position.
Modified code (briefly tested and seems to work):
int bruteforce(const std::string &T, const std::string &P)
{
int n = T.length();
int m = P.length();
for (int i = 0; i <= n-m; ++i) {
int j = 0;
while (j < m && T[i+j] == P[j]) {
++j;
}
if (j == m) { // match found
return i;
}
}
return -1;
}