#include <iostream>
#include <string>
usingnamespace std;
int main()
{
string main, bwd = "", test = "", pass = "";
cin >> main;
for (int j = 0; j < main.length(); j++){
bwd += main.at(main.length() - 1 - j);
}
for (int i = 0; i < main.length(); i++){
test = main.at(i);
size_t found = bwd.find(test);
if (found != string::npos){
string pass_temp = "";
int counter = 1;
while (bwd.find(test) != string::npos){
pass_temp = test;
test += main.at(i + counter);
counter++;
}
if (pass_temp.length() > pass.length()){
pass = pass_temp;
}
}
}
cout << pass << endl;
return 0;
}
The program is crashing with an std:: out_of_range, which I think is happening within the while loop, could anyone give me a nudge in the right direction?
You have a lot of issues here. I'll display a comment with each line and what it is doing, then point out specific issues that are not doing as you expect.
#include <iostream>
#include <string>
usingnamespace std;
int main()
{
string main, bwd = "", test = "", pass = "";
// Allows the user to enter a string
// This only stores the characters up until the first whitespace
// encountered. If you type "I like to drive..." main will contain
// "I". Do some research on cin.getline()
// http://www.cplusplus.com/reference/istream/istream/getline/
cin >> main;
// Runs a loop for the number of characters in main and
// assigns bwd with the reverse of main
// Once the above is fixed, bwd will be "...evird ot ekil I"
// Is this what you really want?
for (int j = 0; j < main.length(); j++){
bwd += main.at(main.length() - 1 - j);
}
// Runs a loop for the number of characters in main
for (int i = 0; i < main.length(); i++){
// test is set to the specific character at i
test = main.at(i);
// this finds the first instance of test, which is
// only one character.
// This will work if you figure out how to change
// test to be set to an entire word
size_t found = bwd.find(test);
// As long as you found a palindrome (currently just
// one character long...which happens a lot)
if (found != string::npos){
// pass_temp is set to empty
string pass_temp = "";
// not sure why this is a while loop when you
// could have just used a for loop
// for (int counter = 0; bwd.find(test) != string::npos; counter ++)
int counter = 1;
// This will be true as long as test is a palindrome
// has the same effect as the above if conditional
while (bwd.find(test) != string::npos){
// pass_temp is assigned the palindrome
pass_temp = test;
// I believe this is your attempt to turn test into a word
// the problem is, the code doesn't know the difference
// between a space and a letter and a period.
// This is also where you're getting your out of range error
// i + counter is going to be >= length
// include that in the conditional of the while or for
test += main.at(i + counter);
counter++;
}
// Set the new password if temp is longer
if (pass_temp.length() > pass.length()){
pass = pass_temp;
}
}
}
cout << pass << endl;
return 0;
}
I was a little confused reading down your code since I was expecting something differently, but just read through it all and you should be able to figure it out.
@Smac89
A lot of people prefer to solve the problems themselves before learning the optimal way of doing the same thing. Also, someone doesn't always learn by just giving them the answer.
Thanks to both for the help, I modified it so it separates the main string into words, and then searches those words in the backwards string, it works as long as the words are separated only by spaces, the only problem is that the challenge gives me a really long string with no spaces to separate words, so I don't think this solution should work.
The most intuitive solution for me is to use 3 for loops. It is a bit of a brute force method, but works. The first is for the starting point, the second is for the end point, and the third is to test if the substring is a palindrome. If you find that you have a palindrome, then check if the length is larger than the longest palindrome found, and if so, print it out.
edit: This solution is only for strings without spaces I believe, you may need a little code at the start to strip away the spaces.
If racecar was the password for your given example, its any valid substring, it doesn't have to be a complete word. That's the part I missed initially. I believe you were actually closer with your first program if thats the case. Another thing you may need to consider is, if the input starts as "Racecars are fast..." Is the password going to be racecar or aceca. The only real changes you needed to make was reading of main using getline, and fixing your out of bounds issue. I also suggest maybe making that inner while loop a for statement as well.
I'm at work right now, but if you can't figure it out by the time I get home, I'll give you the pointers I suggested in coding format. Good luck.
#include <iostream>
usingnamespace std;
bool IsPalindrome(string s)
{
for (int i = 0; i < s.length() / 2; i++)
if (s[i] != s[s.length() - i - 1])
returnfalse;
returntrue;
}
int main()
{
string s = "I like racecars that go fast";
for (int i = s.length(); i >= 2; i--)
for (int j = 0; j <= s.length() - i; j++)
if (IsPalindrome(s.substr(j, i)))
cout << s.substr(j, i) << endl;
return 0;
}
We could try to construct the palindromes instead of searching for them?
Case 1: try to construct palindromes of odd length:
- select a character
- check if left and right match
- check if outer left and right match
- ... and so on, until they don't
- save the palindrome if it's longer than the previous one we err... found
Case 2: palindromes of even length:
- select two neighboring characters which match
- continue as in Case 1
Complexity should be O(2*n2) which is the same as O(n2)?
Or each letter in the string could act like a linked list.
start at index 1 and progress through the string
set a temp linked list at the index 0
If node at index k is equal to node at index k-1
If the (node at index k-1).prevNode != NULL
Node[k-1] = Node[k-1].prevNode
Else Store indexes of longest palindrome string found and temp linked list will now be pointing to current letter the iteration is at
Wow, I wasn't expecting so many replies, thanks everyone for helping, I think my problem was that I didn't really have a solid understanding of strings.
I took a slightly different approach. I built a map of character ranges which indicate possible palindromes, keyed on the length of the possible palindrome (in descending order.) These ranges were generated by finding pairs of the same letter in the string, since every palindrome must begin and end with the same letter. Sequences of 2 letters are discarded as uninteresting. Sequences of more than 2 are filtered; if the 2nd and 2nd to last character in the sequence aren't equal the sequence is discarded, otherwise it is added to the map to be processed as a possible palindrome later.
When that's done, I simply iterated through the map, checking the ranges to see if they were palindromes as I went. Given the order, the first palindrome I found would be the longest.
It's probably a little more complicated than it need be.