Finding no.of times small string is in large string (c++) - c++

I have to implement c++ code to find out the number of occurrences of a small string in a large string with overlapping allowed. For eg- if large string is acacab and small string is aca, then answer should be 2.
I'm not getting correct answer by making this code:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int i, j, k, c=0;
char lstr[30],sstr[10],tstr[10];
cout<<"Enter large string:"<<endl;
cin>>lstr;
cout<<"Enter small string:"<<endl;
cin>>sstr;
for(i=0;i<strlen(lstr);i++)
{
if(lstr[i]==sstr[0])
{
j=i;
for(k=0;k<strlen(sstr);k++,j++)
{
tstr[k]=lstr[j];
}
}
if(strcmp(tstr,sstr)==0)
c++;
}
cout<<c;
return 0;
}

It's much easier if you use C++ strings instead of C ones:
int c=0;
string lstr, sstr;
cout<<"Enter large string:"<<endl;
cin>>lstr;
cout<<"Enter small string:"<<endl;
cin>>sstr;
for (size_t pos = 0;
(pos = lstr.find(sstr, pos)) != string::npos;
pos++)
{
c++;
}
cout<<c;

This should work, add a '\0' to terminate c-style string, and move if(strcmp(tstr,sstr)==0) in the if(lstr[i]==sstr[0]) statement(otherwise you will continuing increment c when lstr[i] != sstr[0]):
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int i, j, k, c=0;
char lstr[30],sstr[10],tstr[10];
cout<<"Enter large string:"<<endl;
cin>>lstr;
cout<<"Enter small string:"<<endl;
cin>>sstr;
for(i=0;i<strlen(lstr);i++)
{
if(lstr[i]==sstr[0])
{
j=i;
for(k=0;k<strlen(sstr) && j<strlen(lstr);k++,j++)
{
tstr[k]=lstr[j];
}
tstr[k] = 0;
// ^^^^^^^^^^^^
if(strcmp(tstr,sstr)==0)
c++;
}
}
cout<<c;
return 0;
}

This will solve your problem more efficiently in O(n*m) complexity, where n is large string size and m is small string size.
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int i, j, k, c=0;
char lstr[30],sstr[10];
cout<<"Enter large string:"<<endl;
cin>>lstr;
cout<<"Enter small string:"<<endl;
cin>>sstr;
for(i=0; lstr[i]; i++) // You don't need to calculate strlen each time. This loop will break when lstr reaches null ('\0') character
{
if(lstr[i]==sstr[0])
{
for(k=0,j=i; sstr[k] && lstr[j]; k++,j++) // don't need to calculate strlen each time
{
if(sstr[k]!=lstr[j]) // Break if not match
break;
}
if(k==strlen(sstr)) // Whole string matched
c++;
}
}
cout<<c<<"\n";
return 0;
}
If you want to solve this problem in O(n) complexity you can use KMP algorithm. Which is the best choice for this kind of problems.

Related

I aim to write a program that will count and store the position of the occurence of a string within a character array

The program will count the position where a specific string occurs within a character array and store that position within an array. As an example the string 'has' would be at positions [0,13,25,33] when compared to the string 'hassan is a hassler who hassles hasslers'. Two main character arrays are being used; str[] and sub[]. str being the string from where the occurrence is counted from and sub the string compared. I have attached my idea of the code. Any help is appreciated and as I am still a student and not a pro, I would very much appreciate constructive help rather than comments on how my code and workflow is sloppy. I wish to display the array with all the positions and the program does not display anything other than the return value, which for some reasons is mostly very big numbers.
#include <iostream>
#include <cstring>
using namespace std;
void allPositionsofSub()
{
int nstr;
int nsub;
char str[100]; //i initially wished to use the variable nstr but it wouldnt work with cin.get
char sub[nsub];
cout<<"Enter the string: ";
cin.get(str, 100);
cout<<"Enter the sub: ";
cin>>sub;
int num;
int count;
int count1=0;
int outdisplay[count];
for(int nstr1=0;nstr1<=99;nstr1++)
{
char n;
n = sub[nstr1];
while (nstr1<=nsub)
{
if (n==str[nstr1])
{
outdisplay[num]=nstr1;// this is where i think the problem perhaps lies.
num++;
count++;
}
}
}
while(count1<=count)
{
cout<<outdisplay[count1]<<", ";
count1++;
}
cout<<"-1";
}
int main()
{
allPositionsofSub();
}
updated code:
#include <iostream>
#include <cstring>
using namespace std;
void allPositionsofSub()
{
int nstr;
int nsub=20;
char str[100];
char sub[20];
cout<<"Enter the string: ";
cin.get(str, 100);
cout<<"Enter the sub: ";
cin>>sub;
int num;
int count;
int count1=0;
int outdisplay[count];
for(int nstr1=0;nstr1<=99;nstr1++)
{
char n;
n = sub[nstr1];
if (n==str[nstr1])
{
outdisplay[num]=nstr1;
num++;
count++;
}
}
while(count1<=count)
{
cout<<outdisplay[count1]<<", ";
count1++;
}
cout<<"-1";
}
int main()
{
allPositionsofSub();
}
So the basic idea is to enumerate over every position in the source string and check whether it is the start of your substring.
It is better for you to try implementing the following pseudo-code, and come back if you have any more questions.
# substr_len: The length of the substring you are looking for.
# str_len: The length of the source string.
# result: An array of int with sufficient length.
let match_count = 0
for (i in range 0..str_len-substr_len)
let match = true
for (j in range 0..substr_len-1)
if (substr[j] != str[i + j])
match = false
break
if (match)
result[match_count] = i
match_count = match_count + 1

find method giving wrong answer in c++

In the following code we have to first calculate the weights of uniform substrings present in our strings . Uniform sub strings are those which contain just one character like "a" or "aaa". The weight of the character is defined as a-1 b-2......z-26.
After calculating the weights of all the valid uniform substrings we will be given with various queries and we have to check whether the given no. is the array or not.
Here is the link of the code and corresponding output to it:
https://www.ideone.com/pIBPtQ
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin>>s;
int i=0,j=0,k=0;
int arr[10000];
int c=0;
while(s[i]!='\0')
{
int x=(int)s[i];
x=x-96;
arr[c++]=x;
j=i+1;
int sum=x;
while(s[j]==s[i])
{
sum+=x;
arr[c++]=sum;
j++;
}
i=j;
}
int q;
cin>>q;
for(i=0;i<q;i++)
{
int val;
cin>>val;
bool exists=find(begin(arr),end(arr),val)!=end(arr);
if(exists==true)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
cout<<"the elements of the array are:"<<endl;
for(i=0;i<c;i++)
cout<<arr[i]<<" ";
return 0;
}
You forgot to initialize arr.
Change
int arr[1000];
to
int arr[1000] = {0};
https://www.ideone.com/wIj4vp
Also x=x-96; should be better written as x -= 'a';.

Why this different behaviour while indexing the array using character?

I am trying to write a c++ program to find the first non-repeated character and if all the characters are repeated it would return -1.
I have designed a solution that keeps track of the count of characters using a integer array which I index using the respective character whose count has to be stored.
Program 1:
Gives erroneous output...
http://ide.geeksforgeeks.org/wxOYog
#include<iostream>
#include<cstring>
using namespace std;
int map[256];
string returnFirstRepeatingChar(string str,int n)
{
int i=0,flag=1;
string result;
for(i=0;i<n;i++)
map[str[i]]++;
for(i=0;i<n;i++)
{
if(map[str[i]]==1)
{
flag=0;
result = str[i];
break;
}
}
if(flag)
return "-1";
else
return result;
}
int main()
{
//code
int t,N,*arr,i,j;
cin>>t;
string str;
while(t--)
{
cin>>N;
memset(&map,0,256);
cin>>str;
cout<<returnFirstRepeatingChar(str,N)<<endl;
}
return 0;
}
Program 2:
Gives correct output...
http://ide.geeksforgeeks.org/jJvJPu
#include<iostream>
#include<cstring>
using namespace std;
int map[256];
string returnFirstRepeatingChar(string str,int n)
{
int i=0,flag=1;
string result;
for(i=0;i<n;i++)
map[str[i]-97]++; //changed from above program
for(i=0;i<n;i++)
{
if(map[str[i]-97]==1) //changed from above program
{
flag=0;
result = str[i];
break;
}
}
if(flag)
return "-1";
else
return result;
}
int main()
{
//code
int t,N,*arr,i,j;
cin>>t;
string str;
while(t--)
{
cin>>N;
memset(&map,0,256);
cin>>str;
cout<<returnFirstRepeatingChar(str,N)<<endl;
}
return 0;
}
Only difference between the two programs is location of required counts in the array map..
In the program 1, it starts from 97 (ascii of a)
In the program 2, it starts from 0.
But program 2 gives correct output, but the program 1 isn't. Why?
Eg: for input: abcdefghij
program 1 output: f
program 2 output: a
One important issue here is this line:
memset(&map,0,256);
Here you are zeroing only the first 256/sizeof(int). In case the sizeof(int) is 4, this makes the first 64 int.
However, your program is using the elements which index is greater than 97, hence the issue appearing.
Hence it should be
memset(&map,0,256*sizeof(int));
or could be also simply written as
memset(map,0,sizeof(map));
Remember: the 3rd parameter of memset is "the number of bytes to fill", not "the number of elements of your array"

Finding the sum of n big numbers

Question: Given a number k, find the sum of k positive big integers.
This is my code,it works, but our Online Judge is rejecting it, says segfault. Why does it show segfault? I could do it with two strings but why isn't this working?
#include <iostream>
#include <string.h>
using namespace std;
void add(int l,int k);
void append(char a[], int temp);
int o;
int tf=0;
int carry=0;
char b[1000000];
char a[10000][10000];
char c[1000000];
int main()
{
int k,x=0,l=0,m=0;
cin>>k;
while(x<k)
{
cin>>a[x];
if(strlen(a[x])>l)
{
l=strlen(a[x]);
}
x++;
}
x=0;
while(x<k)
{
if(strlen(a[x])<l)
{
int temp=0;
append(a[x],l-strlen(a[x]));
}
x++;
}
add(l,k);
if(carry!=0)
{
cout<<carry;
}
while(o>=0)
{
cout<<(int)b[o];
o--;
}
}
void add(int l,int k)
{
int lb=l-1;
int r=k-1;
int sum=0;
int x=0;
int neg=0;
while(lb>=0)
{
r=k-1;
sum=0;
while(r>=0)
{
sum=sum+a[r][lb]-48;
r--;
}
sum=sum+carry;
lb--;
if(sum>=10)
{
b[x]=sum%10;
carry=sum/10;
}
else
{
b[x]=sum;
carry=0;
}
sum=0;
o=x;
x++;
}
}
void append(char a[], int temp)
{
int l=0,m;
int tempb=temp;
m=strlen(a)-1;
while(temp>0)
{
c[l]='0';
l++;
temp--;
}
int z=0;
while(z<=m)
{
c[l]=a[z];
z++;
l++;
}
z=0;
while(z<=m+tempb)
{
a[z]=c[z];
z++;
}
}
Input Format:
First line contains k , which specifies the number of big numbers. Each of the next k lines contains a
big positive integer.
Output Format:
For each test case print the new big integer in a new line
Sample Input:
3
1331331
1313
453535322
Sample Output:
454867966
Constraints:
1<=k<=10
1<=number of digits in big numbers<=10000
Based on the problem statement:
Each input entry my have at most nmax = 10000 digits
Since each entry is stored as a C-style, zero-terminated string, each character array must have a length of (nmax + 1) = 10001 characters, to accomodate for the C-string terminator '\0'.
As you stored the entries into character arrays without leaving room for the zero terminator, assuming each entry was 10000-characters long:
Each entry with k>=1 overwrote the terminator or entry k-1, thus coalescing the entries together;
You thus ended with one giant string, with l = strlen(a[0]) = 100000;
From then on, all further processings were performed with these incorrect (coalesced) inputs and length, leading to buffer overrun at some point later in the execution.

Read a sequence of words from input. Use "Quit" to terminate, print in order they were entered and don't print a word twice.

It would be great if someone can provide a better code than mine, in spite of working it also sucks. Also, there is a problem with my code!! When I print my new array arr, in output the positions of array is skipped when there is a duplicate word, and it outputs an empty space for that.
For example:
bat,
cat,
mat,
//here the word bat is not printed again, but instead i get an empty space
rat,
quit,
Also please only use pointers, array or strings, because I have yet to study vectors, lists, maps and such. Thank you.
#include<iostream>
#include<conio.h>
#include<string>
using namespace std;
int main()
{
string word[100];
string arr[100];
int i=0,j,k,m,n;
while(1)
{
cout<<"enter word: \n";
cin>>word[i];
if(word[i]=="quit")
break;
i++;
}
for(j=i,m=0;j>=0,m<=i;m++)
{
for(k=j-1;k>=0;k--)
{
if(word[j] == word[k])
goto start;
}
arr[m]=word[j];
start:
j--;
}
for(n=m;n>0;n--)
cout<<arr[n]<<"\n";
getch();
}
Fixed a little, I didn't wanted to spend time to understand your for(j=i,m=0;j>=0,m<=i;m++) cycle so fully rewrited it.
#include<iostream>
#include<conio.h>
#include<string>
using namespace std;
int main()
{
string word[100];
string arr[100];
int wordCount = 0;
while(1)
{
cout<<"enter word: \n";
cin>>word[wordCount];
if(word[wordCount] == "quit")
{
break;
}
++wordCount;
}
int arrCount = 0;
for(int i = 0; i < wordCount; ++i)
{
bool found = false;
for (int j = 0; j < arrCount; ++j)
{
if (arr[j] == word[i])
{
found = true;
break;
}
}
if (!found)
{
arr[arrCount] = word;
++arrCount;
}
}
for(int i = 0; i < arrCount; ++i)
{
cout<<arr[n]<<"\n";
}
getch();
}
And never use goto, your teatcher will be very angry if he see it.