Why does this code output different results for the same inputs? - c++

I wrote a simple program to find the longest sub-string with distinct characters in a given string in C++. My code works for certain inputs, but doesn't for others. Moreover, it gives me different outputs for the same inputs. Where am I going wrong?
int main() {
int t;
cin >>t;
while(t--){
string s;
cin >> s;
int n = s.length();
int maxlen = 0;
for(int i = 0; i < n; i++){
int count = 0;
int arr[26] = {0};
bool isDist = true;
int j = i;
while(isDist){
if(arr[(int)s[j] - (int)'a'] == 0){
count++;
arr[(int)s[j] - (int)'a'] = 1;
j++;
} else {
isDist = false;
}
}
if(count > maxlen) maxlen = count;
}
cout << maxlen << endl;
}
return 0;
}
for the following input:
3
aewergrththy
aewergrththy
aewergrththy
My code outputs:
5
4
4
Any help is appreciated, Thank you!

The problem is that there is no check that j remains less than n, so you start checking characters beyond the end of your string, leading to in unpredictable results. Try
while (isDist && j < n)
That should help but I haven't checked the rest of your code for errors.
You could also consider using s.at(j) instead of s[j]. That at least results in predictable behaviour when going out of bounds, at throws an exception in that case.

The program has undefined behavior because you do not bounds-test when iterating over the string with j. You should modify the inner loop to test for j in addition to isDist:
while(isDist && j < n)
Without this, it's very easy for j to shoot past the end of the string as soon as all remaining characters in the string have not yet been encountered.
In this case, it will be when you process the character 'y' at the end of the string. After dealing with 'y', you'll advance j such that s[j] returns the string terminator. Now, you'll be accessing the array with arr[0 - 'y'] which of course is undefined behavior due to being a negative index.

Related

What can I use to stop a loop instead of 'return 0'?

so I made a simple loop that finds out if an array has the elements with the values of 0 and 1.
if the loop indeed finds 0 or 1 inside of the array, it will say "YES", otherwise "NO".
yes, the program works just fine, but at the end of the program it prints out "YES" or "NO" as many times as i put cin>>dim to.
for example if dim which means (dimension[of the array]) is 5 it's going to print either "YESYESYESYESYES" or "NONONONONO"
I have to use return 0 in order to make it print it out like once, but I feel like this is not the right way to do it. Please help me with this. thanks!
#include <bits/stdc++.h>
using namespace std;
int main()
{
int i, dim, v[100];
cin>>dim;
for(i=0;i<dim;i++)
cin>>v[i];
for(i=0;i<dim;i++)
if(v[i]==0 || v[i]==1){
cout<<"YES"; return 0;}
else{
cout<<"NO"; return 0;}
return 0;
}
The break statement can be used to break out of loops. The example from cppreference:
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 5; k++) { //only this loop is affected by break
if (k == 2) break;
std::cout << j << k << " ";
}
}
As the comment suggests, break only breaks the innermost loop.
In your code you always exit from the loop on the very first iteration, hence you do not need the loop in the first place. This will have the same output as your code:
int main() {
int i, dim, v[100];
cin >> dim;
for(i=0; i < dim; i++)
cin >> v[i];
if(v[0] == 0 || v[0] == 1) {
cout << "YES";
} else {
cout << "NO";
}
}
After reading the question again...
I made a simple loop that finds out if an array has the elements with the values of 0 and 1
If you exit the loop after checking the first element then you only check the first element. If you want to see if an array contains only 1 or 0 or it contains at least one element which is 0 or 1 (not 100% clear which one you want), then you rather need this:
bool only_zero_or_one = true;
bool one_zero_or_one = false;
for (int i = 0; i < dim; ++i) {
zero_or_one = ( v[i] == 0 | v[i] == 1);
only_zero_or_one = zero_or_one && only_zero_or_one;
one_zero_or_one = zero_or_one || one_zero_or_one;
}
Only for one_zero_or_one you can break the loop once zero_or_one == true.
Moreover, you should rather use a std::vector. In your code, if the user enters a dim which is greater than 100 you write beyond the bounds of v. This can be avoided easily:
size_t dim;
std::cin >> dim;
// construct vector with dim elements
std::vector v(dim);
// read elements
for (size_t i=0; i < v.size(); ++i) std::cin >> v[i];
// .. or use range based for loop
for (auto& e : v) std::cin >> e;
but I feel like this is not the right way to do it
Returning is an entirely right way to break out from a loop.
Another right way is the break statement, which jumps to after the loop.
Even better, you can actually check if v[i]==0 or 1 inside the input for loop immediately after taking input and set a flag to true. Depending on requirement, you can either break or wait until the entire input is read and then come out and check for flag==true and then print "YES" and print "NO" if flag==false.
This will save you running the loop again to check for 0 or 1.

Having Trouble With The Reversal of a String

class Solution {
public:
string reverseWords(string s) {
int previousWhiteSpace = 0;
for(int i = 0; i <= s.size(); i ++){
if(isspace(s[i]) || i == s.size()){
for(int j = previousWhiteSpace; j < i/2; j++){
char temp = s[j];
s[j] = s[i-1-j];
s[i-1-j] = temp;
}
previousWhiteSpace = i + 1;
}
}
return s;
}
};
Hi. So the goal of my function is to reverse the input of a string. So for example, if I am given "Let's take LeetCode contest" , my function should return "s'teL ekat edoCteeL tsetnoc" . However, currently my function is ONLY returning
"s'teL take LeetCode contest" . I have a counter which I indicate as previousWhiteSpace to keep track of the start of every new word that seems to work for the first word, but not the rest. Any help would be appreciated.
You can simply assign " " to the variable previousWhiteSpace and no need to increment. thus your code will detect white space automatically till the end of the string and will run the code after every white space. As you have assigned value 0 to it will only perform the result for the first word and it will terminate.

How is this line returning the length of the array in recursion?

I am trying to understand this recursion using the debugger and trying to understand it step by step the main.The debugger shows the smallAns returns the size of the array I can't understand how this smallAns is returning the size of the array input[].can anyone explain this
#include<iostream>
using namespace std;
int subsequences(char input[], int startIndex,char output[][50]){
if(input[startIndex] == '\0'){
output[0][0] = '\0';
return 1;
}
int smallAns = subsequences(input, startIndex+1, output);
for(int i = smallAns; i < 2*smallAns; i++){
int row = i - smallAns;
output[i][0] = input[startIndex];
int j = 0;
for(; output[row][j] != '\0'; j++){
output[i][j + 1] = output[row][j];
}
output[i][j + 1] = '\0';
}
return 2*smallAns;
}
int main(){
char input[] = "abc";
char output[100][50];
int ans = subsequences(input, 0, output);
for(int i = 0; i < ans; i++){
for(int j = 0; output[i][j] != '\0'; j++){
cout << output[i][j];
}
cout << endl;
}
}
Here's what the algorithm is doing:
Start at the end, with the empty subsequence (or "\0"). You have 1 subsequence.
Look at the last character not yet considered. For all the subsequences you have found, you can either add this last character, or don't. Therefore you have doubled the number of subsequences.
Repeat.
Therefore, 2 * smallAns means "Take the number of subsequences found in the lower recursive call, and double it." And this makes sense after you know how it was implemented. Thus the importance of comments and documentation in code. :)

Getting WA for SPOJ smpseq

Here is the link to the question: http://www.spoj.com/problems/SMPSEQ3/
I am getting WA every time although the code works for all of the test cases I have tried
Please give me a hint.I am a beginner in this
This is my code.
#include<iostream>
using namespace std;
int main()
{
int n, m;
bool check;
int cnt=0;
cin >> n;
int s[n];
int c[n];
for(int i = 0; i < n; i++)
cin >> s[i];
cin >> m;
int q[m];
for(int i = 0; i < m; i++)
cin >> q[i];
for(int i = 0; i < n; i++)
{
check = false;
int j = 0;
while(q[j] <= s[i])
{
if(q[j] == s[i])
check = true;
j++;
}
if(check == false)
{
c[cnt] = s[i];
cnt++;
}
}
for(int i = 0; i < cnt; i++)
cout << c[i] << " ";
return 0;
}
You code fails because you do not keep a check on the value of j whether it is less than m or not, you simply keep on incrementing it until you hit a value where q[j] <= s[i]. So, when your j becomes m in the while loop, you are actually accessing memory which was not allocated to you, and there is some garbage value stored there. Since the garbage value can be anything you might eventually miss some values in q[] which should be added to c[].
So, your while condition shall look like this ::
while(j < m && q[j] <= s[i])
I think this shall give you an AC.
A few more things you initialize j = 0 every time you enter the for loop, which is useless. Since in the question it is given that both the sequences are sorted, so considering the sequences ::
S = a, b, c, d . . .
Q = aa, bb, cc, dd . . .
So, considering if aa < a but bb > a so, in the first iteration your j stops at bb. So, now when i comes at b in S, since a > aa and b >= a(S is a sorted sequence), so b > aa as well. So, you do not need to initialize j = 0 at the beginning of every iteration, which will save you wasteful computations. You just need to initialize j = 0 at beginning of the main.
Moreover, you do not need to save the result in a new array, you can simply print it, when you encounter check == false, this save you some space.

Boyer Moore k-mismatches algorithm fails

I've done a program for string comparison with one mismatch at a programming website. It gives me wrong answer. I've working on it extensively but, I couldn't find testcases where my code fails. Can somebody provide me test cases where my code fails. I've done the comparison using Boyer Moore Horspool k-mismatches algorithm as it's the fastest searching algorithm
The code is as such
int BMSearch_k(string text, string pattern, int tlen, int mlen,int pos)
{
int i, j=0,ready[256],skip2[256][mlen-1],neq;
for(i=0; i<256; ++i) ready[i] = mlen;
for(int a=0; a<256;a++) {
for(i = mlen;i>mlen-k;i--)
skip2[i][a] = mlen;
}
for(i = mlen-2;i>=1;i--) {
for(j=ready[pattern[i]]-1;j>=max(i,mlen-k);j--)
skip2[j][pattern[i]] = j-i;
ready[pattern[i]] = max(i,mlen-k);
}
j = mlen-1+pos;
//cout<<"\n--jafffa--\n"<<pos<<"+"<<mlen<<"="<<j<<endl;
while(j<tlen+k) {
//cout<<"\t--"<<j<<endl;
int h = j;
i=mlen-1;
int neq=0,shift = mlen-k;
while(i>=0&&neq<=k) {
//cout<<"\t--"<<i<<endl;
if(i>=mlen-k)
shift = min(shift,skip2[i][text[h]]);
if(text[h]!= pattern[i])
neq++;
i--;
h--;
}
if(neq<=k)
return j-1;
j += shift;
}
return -1;
}
You aren't initialising your arrays correctly,
int i, j=0,ready[256],skip2[256][mlen-1],neq;
for(i=0; i<256; ++i) ready[i] = mlen;
for(int a=0; a<256;a++) {
for(i = mlen;i>mlen-k;i--)
skip2[i][a] = mlen;
}
On the one hand, you declare skip2 as a 256×(mlen-1) array, on the other hand, you fill it as a (mlen+1)×256 array.
In the next loop,
for(i = mlen-2;i>=1;i--) {
for(j=ready[pattern[i]]-1;j>=max(i,mlen-k);j--)
skip2[j][pattern[i]] = j-i;
ready[pattern[i]] = max(i,mlen-k);
}
you use ready[pattern[i]] before it has been set. I don't know if those mistakes are what's causing the failing testcase, but it's easily imaginable that they do.
If Daniel's suggestions do not solve the problem, here are a couple more things that look odd:
return j-1; // I would expect "return j;" here
This seems odd as if you have k=0,mlen=1, then the highest value that j can take is tlen+k-1, and so the highest return value is tlen-2. In other words matching a pattern 'a' against a string 'a' will not return a match at position 0.
Another oddity is the loop:
for(i = mlen-2;i>=1;i--) // I would expect "for(i = mlen-2;i>=0;i--)" here
it seems odd that in the preprocessing you will never access the first character in your pattern (i.e. pattern[0] is not read).