Finding the longest palindromic substring (suboptimally) - c++

I'm working on a coding exercise that asks me to find the longest palindromic substring when given an input string. I know my solution isn't optimal in terms of efficiency but I'm trying to get a correct solution first.
So far this is what I have:
#include <string>
#include <algorithm>
#include <iostream>
class Solution {
public:
string longestPalindrome(string s) {
string currentLongest = "";
for (int i = 0; i < s.length(); i++)
{
for (int j = i; j <= s.length(); j++)
{
string testcase = s.substr(i, j);
string reversestring = testcase;
std::reverse(reversestring.begin(), reversestring.end());
if (testcase == reversestring)
{
if (testcase.length() > currentLongest.length())
{
currentLongest = testcase;
}
}
}
}
return currentLongest;
}
};
It works for several test cases, but also fails on a lot of other test cases. I suspect something is going wrong in the most inner loop of my code, but am not sure exactly what. I'm attempting to generate all possible substrings and then check if they are palindromes by comparing them with their reverse; after I establish they are a palindrome I check if it's longer than the current longest palindrome I have found.

because you are not trying all the possible solution
in c++ , substr takes two parameters the first are the starting index , and the second is the length of the substring
how ever in you program you don't check for the string which starts at index 4 and have length of three for example
in the second for loop you shoud start from index 1 not from index i

Related

Finding if a string is contained in another string without "find" in c++

I wrote this program to find if a string is contained in another string (see paragraph below this, I tried to explain what I want it to do). When I test it, sometimes it works, most of the times it gives me the error "String subscript out of range". I'm very new to C++, I'd appreciate someone to tell me how can I improve this code or why I'm being dumb, because I really don't get why it doesn't work.
what i want this to do is find if string one can be found in string way;
so i want it to check for every letter of string way if the letter [i] is equal to the first letter of the string one (way[i+0]==one[0]),
and way[i+1]==one[1] and so on for all letters in one.
so for example way = abankjve and one = ank
it takes the first letter in way (a) and gets the first letter in one(a). the're equal. but we see that way[0+1] is not equal to one[1]. so o can't be true.
it goes on like this till it gets to way[2]=a. way[2+0]=one[0]. o is true. then it checks way[2+1]=one[1]. true! then it checks way[2+2]=one[2]. true! then
one is contained in way.
#include <iostream>
using namespace std;
int main()
{
string way, one;
bool o=false;
cin >> way;
cin >> one;
for (int i = 0; i < way.size(); i++)
{
for (int k = 0; k < one.size(); k++)
{
if (way[i + k]==one[k])
{
o = true;
}
}
}
cout << o << endl;
}
If you think about it, way[i+k] will result in index out of range.
say way is length of 5 and one is length of 3.
i+k's range is 0 <= i + k <= 6. Witch is bigger than the possible index of way.
change first for loop for (int i = 0; i < way.size(); i++) to
for (int i = 0; i <= (int)way.size() - one.size(); i++)
Note I've used static_cast to int. *.size() returns unsigned int so if one's size is bigger than way's size, the result won't be what you've imagined.
#include <iostream>
#include <string>
int main()
{
std::string way, one;
std::cin >> way;
std::cin >> one;
bool found{};
for (size_t i = 0; i < way.size() - one.size()+1; i++)
{
if(one == way.substr(i, one.size())) {
found = true;
break;
}
}
std::cout << found;
}
Demo

Find Longest common Substring

I need to find longest common substring from two DNA strings.
I have first string "CGATAC", and second: "GACAGTC"
With my code my result is: "GAC", but you can get longer substring, i mean "GATC". What i need to change to get longer substring ?
int k = 0;
for (int i = 0; i < substring1.length(); i++) {
char znak = substring1[i];
for (int j = k; j < substring2.length(); j++) {
char znak2 = substring2[j];
if (znak == znak2) {
end_substring += znak;
k = j;
break;
}
}
}
cout << end_substring;
You can improve your code with some basic ideas. I understand you want one of the longest strings, not all, then you can store the length of the longest string until each moment in the program, and use this length for search string at least of length+1. But the bes solution is use dynamic porgramming, you can read this solution here: https://www.geeksforgeeks.org/longest-common-substring-dp-29/

Printing all longest matching substrings

I have an assignment for finding all of the longest matching sub-strings between the strings "B D C A B A" and "A B C B D A B". There are a lot of partial solutions to this online but none that do what I need them to. I created this to find one longest matching sub-string, but I need to be able to find all of them, there should be 6 in total.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void myLMS(string one, string two);
int main()
{
string s1 = "ABCBDAB";
string s2 = "BDCABA";
myLMS(s1, s2);
return 0;
}
void myLMS(string one, string two) {
vector<vector<char>> lms;
vector<char> one_lms;
for (int i = 0; i < two.length(); i++) {
for (int j = i + 1; j < one.length(); j++) {
if (two[i] == one[j]) {
one_lms.push_back(two[i]);
break;
}
}
}
lms.push_back(one_lms);
for (int i = 0; i < lms[0].size(); i++) {
cout << lms[0][i];
}
}
Is there a way for me to continue with this method and get the outcome I'm looking for or is another approach needed?
Edit: I found this solution https://www.geeksforgeeks.org/printing-longest-common-subsequence-set-2-printing/
but I'm not really interested in just copying from a program as that doesn't really help me. It also only accomplishes half of what I'm trying to do.
From the assignment prompt it looks like the first three strings printed from this example are there as well as the same three only backwards. Reversing the strings doesn't get those backwards sub-strings so how would they be calculated?
Your logic is incomplete by quite a bit. Here's some pseudo-code to help you get started.
for each character in string 1
for each character in string 2
if char_1 == char_2
possible substring match
do the next chars match?
yes
there is a substring - now find longest
no
no substring match, continue the loop
I can't understand what's the need to solve it in this manner since your input strings are fixed you run for loops from first char of one string to last -1 char and and run another nested for loop for each subsequent characters if a match is found like the program of finding out common substring that all of us have done in the beginning.

Finding Randomly Order Substring in String

For my first part of the question, We have given a long string of input and we have to count the occurrence for it.
For eg.
Input = AXBHAAGHXAXBH
Find = AXBH
Output = 2
This can be achieved by using the string.find("term") loop. Eg.
#include <string>
#include <iostream>
int main()
{
int occurrences = 0;
std::string::size_type pos = 0;
std::string inputz = "AXBHAAGHXAXBH";
std::string target = "AXBH";
while ((pos = inputz.find(target, pos )) != std::string::npos) {
++ occurrences;
pos += target.length();
}
std::cout << occurrences << std::endl;
}
However, I am not sure how to do the second part where, it needs to take into account the random structure:
Random structure refers to any orientation of our find. Important note: The find occurrences are always grouped together but can have different structure.
I do not want to use cases because some sample find are too big eg. Find AXBHNMB would have too many cases to consider and would prefer a more general approach.
Eg. AXBH is find, then AXHB is also acceptable for the occurence
A proper example:
Input = AXBHAAGHXAXBH**ABHX**NBMN**AHBX**
Find = AXBH
Output = 4
Prefer if you please code it for the given example with link to explanation/explanation to any new function you use.
You are correct that checking all permutations would take a lot of time. Fortunately we don't need to do that. What we can do is store the string to find in a std::map<char, int>/std::unordered_map<char, int> and then grab sub strings from the string to search through, convert those into the same type of map and see if those maps are equal. This lets use compare without caring about the order, it just makes sure we have the correct amount of each character. So we would have something like
int main()
{
std::string source = "AHAZHBCHZCAHAHZEHHAAZHBZBZHHAAZAAHHZBAAAAHHHHZZBEWWAAHHZ ";
std::string string_to_find = "AAHHZ";
int counter = 0;
// build map of the characters to find
std::unordered_map<char, int> to_find;
for (auto e : string_to_find)
++to_find[e];
// loop through the string, grabbing string_to_find chunks and comparing
for (std::size_t i = 0; i < source.size() - string_to_find.size();)
{
std::unordered_map<char, int> part;
for (std::size_t j = i; j < string_to_find.size() + i; ++j)
++part[source[j]];
if (to_find == part)
{
++counter;
i += string_to_find.size();
}
else
{
++i;
}
}
std::cout << counter;
}
A naive approach is to iterate over the given string and searching the target string.
In each chunk, we need to sort the portion and compare if it matches with the target string.
#include <string>
#include <iostream>
#include <algorithm>
int main()
{
int occurrences = 0;
std::string::size_type pos = 0;
std::string inputz = "AXBHAAGHXAXBH**ABHX**NBMN**AHBX**";
std::string target = "AXBH";
std::sort(target.begin(), target.end());
int inputz_length = inputz.length();
int target_length = target.length();
int i=0;
for(i=0; i<=inputz_length-target_length; i++)
{
std::string sub = inputz.substr(i, target_length);
std::sort(sub.begin(), sub.end());
if (target.compare(sub) == 0)
{
std::cout << i<<"-->"<< target<<"-->" << sub << std::endl;
occurrences++;
i=i+target_length;
}
}
std::cout << occurrences << std::endl;
return 0;
}
Output:
0-->ABHX-->ABHX
9-->ABHX-->ABHX
15-->ABHX-->ABHX
27-->ABHX-->ABHX
4
Extra function: Uses sort function from algorithm header file.
Time complexity: more than O(n2)
One solution is to find a canonical representation for both the search string and a substring. Two fast approaches are possible.
1) Sort the substring.
2) Calculate a histogram of letters.
Option 2 can be calculated incrementally by incrementing histogram bins for the incoming letters and decrementing the bins for outgoing letters in the search window.
While updating the histogram bin, one can also check if this particular update toggles the overall matching:
// before adding the incoming letter
if (h[incoming] == target[incoming]) matches--;
else if (++h[incoming] == target[incoming]) matches++;
// before subtracting outgoing letter
if (h[outgoing] == target[outgoing]) matches--;
else if (--h[outgoing] == target[outgoing]) matches++;
if (matches == number_of_unique_letters) occurences++;
Then the overall complexity becomes O(n).

independent things influence each other (I have no idea what is going on)

Sorry for the title, but I really have no idea what the problem is. The code looks like that (here it has no sense, but in the bigger project is has, so please, do not ask "why do you want to do....")
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
string sort (string slowo){
string litery = slowo;
for (int i=0; i<litery.length()-1; i++)
for (int j=0; j<litery.length()-1; j++)
if (litery[j]>litery[j+1])
swap(litery[j], litery[j+1]); // (3)
return litery;
}
int main()
{
fstream wordlist;
wordlist.open("wordlist_test",ios::in);
vector<string> words;
while (!wordlist.eof()){ // (4)
bool ok = true;
string word;
getline(wordlist,word);
string sorted = sort(word);
if (ok){
cout<<word<<endl; // (1)
words.push_back(word);
}
}
for (int i = 0; i<words.size(); i++){
cout<<words[i]<<endl; // (2)
}
}
There are for words in file "wordlist_tests". Program at the end should just write them to vector and write what's in vector into standard output. The problem is:
however line(1) proves that all words are ok
vector appears to be
empty in line (2)
now iteresting (probably just for me) part:
there are two ways to make it right:
I can just remove line(3) (however, if I am right, as the variable is passed to sort function through the value, it just swap two letters in independent variable; it has nothing to do with my vector), or:
I can change condition in while loop (4).
for example just like this:
int tmp = 0;
while (tmp < 5){
tmp++;
/..../
What is wrong with this code? What should I do write these words down to vector but still sort them and using this while loop? I cannot find the connection between this things (ok, I see that connection is variable word, but I do not know in what way). Any help appreciate.
What happens in swap() if one of the words is the empty sting ""?
If this happens, litery = "".
The condition in the loops will be to iterate from 0 to (unsigned) 0 - 1, which is a very large number.
You'll then execute if (litery[0] > litery[1])
litery[1] will access beyond the end of the empty string, which causes undefined behavior.
Let's fix this:
The common fix for this, is to iterate from 1 to string.length(). Here's an example:
string sort (string litery){
for (int i=1; i<litery.length(); i++)
for (int j=1; j<litery.length(); j++)
if (litery[j-1]>litery[j])
swap(litery[j-1], litery[j]);
return litery;
}