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

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;
}

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;
}

Why does function return garbage values including the real output and how to clear that garbage?

I have written a substring function that takes a value char array, initial value, and length and then return a substring
char* substring(char t[],int i,int l){
int k=0;
char* subs=new char[l];
while(t[k]!=0){
if(k==i){
int a=i;
int j=0;
// for (int j=0;j<l;j++)
while(j<l)
{
subs[j]=t[a];
a++;
j++;
}
if(subs!=0){
break;
}
}
k++;
}
return subs;
}
// CHECKING
int main(){
char t[20]="this is a string";
cout<<substring(t,0,4);
}
//OUTPUT
thisâ””
everything is working properly getting exact output which I want but at the end of the output value it also return a unexpected value such as symbols and random alphabets don't know how to get rid of it
**NOTE I don't want to use strings or anything else just want to clear the problem which in this programme
This is about the smallest change to fix your function -- changing the allocation size, and terminating the substring. You might want to consider whether the outer loop is worthwhile -- shouldn't you return an empty string rather than an uninitialized one if the substring starts after the end of the string? Or should you return a null to signify the error?
It is a matter of style, but the inner loop might be easier to read as:
for (j = 0; j < l; j++) { subs[j] = t[i+j]; }.
char* substring(char t[], int i, int l)
{
int k = 0;
char* subs = new char[l + 1];
while (t[k] != 0) {
if (k == i) {
int a = i;
int j = 0;
// for (int j=0;j<l;j++)
while (j < l) {
subs[j] = t[a];
a++;
j++;
}
subs[j] = '\0';
break;
}
k++;
}
return subs;
}
// CHECKING
int main()
{
char t[20] = "this is a string";
cout << substring(t, 0, 4);
}

How can i search a pattern in a string and return an iterator?

i want to find a pattern inside a string.using brute-force algorithm
int match(string p, string t) {
size_t n = t.size(), i = 0;
size_t m = p.size(), j = 0;
while (i < n && j < m) {
if (p[j] == t[i]) {
j++; i++;
}
else {
i -= j - 1;
j = 0;
}
}
return i - j;
}
but i am wondering how it worked in std::find_if.If there is a string "abab"and i will find "ab" Should i write my code like thisstring::iterator it=find_if(s.begin(),s.end(),match)? but it does not work,How should i write my code and tell me why?
The title says you want to return an iterator. Iterators can be const or not. Declare two overloads and let the compiler sort it out.
std::string::iterator
match( std::string &p, const std::string& t) {
return (p.begin() + p.find(t));
}
std::string::const_iterator
match( const std::string &p, const std::string& t) {
return (p.begin() + p.find(t));
}

Function not declared in the scope (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.

How can I pass a substring by reference?

I call recursively a function passing as argument a substring which always starts from the beginning of the current string up to a position. If I was using C, I could pass the pointer to the first position of the string and then the necessary length. Nevertheless, I would like to achieve the same result using the class string. Is it possible? If I use const, is the compiler smart enough to make the optimization on its own? Even better, is there a way to check on my own whether the compiler actually makes a copy of the argument or passes a reference?
My question was motivated after having written the following code which passes the tests on problem Alphacode on poj, once someone uses atoi instead of atof.
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <string>
using namespace std;
map<string, int> cache;
bool valid_character_number(string a) {
return 0 < stoi(a.substr(a.size() - 2, 2)) && stoi(a.substr(a.size() - 2, 2)) <= 26;
}
bool zero_last_digit(string a) {
return a[a.size() - 1] == '0';
}
bool zero_before_last_digit(string a) {
return a[a.size() - 2] == '0';
}
int decodings(string a) {
if (a.size() == 0)
return 1;
if (a.size() == 1) {
if (zero_last_digit(a))
return 0;
else
return 1;
}
if (cache.find(a) != cache.end())
return cache[a];
if (zero_last_digit(a) && valid_character_number(a))
return cache[a] = decodings(a.substr(0, a.size() - 2));
else if (valid_character_number(a) && !zero_before_last_digit(a))
return cache[a] = decodings(a.substr(0, a.size() - 1)) + decodings(a.substr(0, a.size() - 2));
else
return cache[a] = decodings(a.substr(0, a.size() - 1));
}
int main() {
string input;
while (true) {
cin >> input;
if (input.size() == 1 && stoi(input) == 0)
return 0;
cout << decodings(input) << endl;
}
return 0;
}
You cannot use std::string for this purpose, but you can easily make a class of your own that holds a pair of iterators (begin and end) into another string, or a C-style char* and size. With C++11 (since you tagged it), you should even be able to make a User Defined Literal syntax for creating strings of your new type.
You can use your own wrapper class like this one:
struct RefString
{
RefString(const std::string & s, int i, int l) : s(s), i(i), l(l) {}
const char & operator [] (int x) const {
return s[i+x];
}
size_t length() const {
return l;
}
bool operator < (const RefString & s2) const {
return s.compare(i, l, s2.s, s2.i, s2.l) < 0;
}
private:
const std::string & s;
int i;
int l;
};
std::ostream & operator << (std::ostream &stream, const RefString & ms) {
for (int i = 0; i < ms.length(); i++)
stream << ms[i];
return stream;
}
And use it like this, for example for creating set of unique substrings:
std::string s = "hello";
std::set<RefString> st;
for (int i = 0; i < s.length(); i++)
for (int j = i; j < s.length(); j++)
st.insert(RefString(s, i, j-i+1));