Find longest Palindrome substring

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
2
down vote

favorite












I am preparing for technical interview and I found this question on geeksforgeeks, but I did not understand their solution. So, I have written my own solution. I want to optimize this code.



#include <iostream>
#include <string>

bool isPalindrome(std::string& str)

for (int i = 0, j = str.length()-1; i<j; ++i, --j)

if (str[i] != str[j])

return false;


return true;


int longestPalindrome(std::string& str, std::string& palindromeStr)

int max = 0, start = 0, end = 0;
for (int i = 0; i < str.length(); ++i)

for (int j = i+1; j < str.length(); ++j)

std::string sub = str.substr(i, j);
if (isPalindrome(sub) && max < sub.length())

max = sub.length();
start = i;
end = j;



palindromeStr = str.substr(start, end);
return max;


int main()

std::string str = "forgeekskeegfor";
std::string palindromeStr;
std::cout << longestPalindrome(str, palindromeStr) << 'n';
std::cout << palindromeStr << 'n';










share|improve this question

























    up vote
    2
    down vote

    favorite












    I am preparing for technical interview and I found this question on geeksforgeeks, but I did not understand their solution. So, I have written my own solution. I want to optimize this code.



    #include <iostream>
    #include <string>

    bool isPalindrome(std::string& str)

    for (int i = 0, j = str.length()-1; i<j; ++i, --j)

    if (str[i] != str[j])

    return false;


    return true;


    int longestPalindrome(std::string& str, std::string& palindromeStr)

    int max = 0, start = 0, end = 0;
    for (int i = 0; i < str.length(); ++i)

    for (int j = i+1; j < str.length(); ++j)

    std::string sub = str.substr(i, j);
    if (isPalindrome(sub) && max < sub.length())

    max = sub.length();
    start = i;
    end = j;



    palindromeStr = str.substr(start, end);
    return max;


    int main()

    std::string str = "forgeekskeegfor";
    std::string palindromeStr;
    std::cout << longestPalindrome(str, palindromeStr) << 'n';
    std::cout << palindromeStr << 'n';










    share|improve this question























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I am preparing for technical interview and I found this question on geeksforgeeks, but I did not understand their solution. So, I have written my own solution. I want to optimize this code.



      #include <iostream>
      #include <string>

      bool isPalindrome(std::string& str)

      for (int i = 0, j = str.length()-1; i<j; ++i, --j)

      if (str[i] != str[j])

      return false;


      return true;


      int longestPalindrome(std::string& str, std::string& palindromeStr)

      int max = 0, start = 0, end = 0;
      for (int i = 0; i < str.length(); ++i)

      for (int j = i+1; j < str.length(); ++j)

      std::string sub = str.substr(i, j);
      if (isPalindrome(sub) && max < sub.length())

      max = sub.length();
      start = i;
      end = j;



      palindromeStr = str.substr(start, end);
      return max;


      int main()

      std::string str = "forgeekskeegfor";
      std::string palindromeStr;
      std::cout << longestPalindrome(str, palindromeStr) << 'n';
      std::cout << palindromeStr << 'n';










      share|improve this question













      I am preparing for technical interview and I found this question on geeksforgeeks, but I did not understand their solution. So, I have written my own solution. I want to optimize this code.



      #include <iostream>
      #include <string>

      bool isPalindrome(std::string& str)

      for (int i = 0, j = str.length()-1; i<j; ++i, --j)

      if (str[i] != str[j])

      return false;


      return true;


      int longestPalindrome(std::string& str, std::string& palindromeStr)

      int max = 0, start = 0, end = 0;
      for (int i = 0; i < str.length(); ++i)

      for (int j = i+1; j < str.length(); ++j)

      std::string sub = str.substr(i, j);
      if (isPalindrome(sub) && max < sub.length())

      max = sub.length();
      start = i;
      end = j;



      palindromeStr = str.substr(start, end);
      return max;


      int main()

      std::string str = "forgeekskeegfor";
      std::string palindromeStr;
      std::cout << longestPalindrome(str, palindromeStr) << 'n';
      std::cout << palindromeStr << 'n';







      c++ strings interview-questions






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 1 hour ago









      coder

      898428




      898428




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          4
          down vote













          The code is reasonably clear and obvious, but has some severe inefficiencies.



          First, let's pick up some simple oversights. Both isPalindrome() and longestPalindrome() ought to have internal linkage (either using the static keyword, or in the anonymous namespace), and the str arguments should be reference to const:



          namespace 

          bool isPalindrome(const std::string& str)




           int longestPalindrome(const std::string& str, std::string& palindromeStr)







          The next oversight is that std::string::length() returns a std::size_t, so don't compare it with (signed) int:



          for (std::size_t i = 0, j = str.length()-1; i<j; ++i, --j)
          // ^^^^^^^^^^^


          Note that I've left a bug there (that's neatly missed because we always call this with a non-empty string): if str.length() is zero, then j starts at a very large positive value (because the subtraction is unsigned, and wraps).



          BTW, there's a neat way to test a string for symmetry (at the expense of repeating the initial comparisons), using <algorithm>:



          static bool isPalindrome(const std::string& str)

          return std::equal(str.begin(), str.end(), str.rbegin());




          Now to the matter of efficiency. We're creating new string objects for every possible substring of the input. That's a lot of copying. We could reduce that by using std::string_view.



          That's only part of the way towards an efficient solution, though. We really need to change the algorithm. My recommendation is to iterate over each character as a possible mid-point of an embedded palindrome, and at each position, determine what's the longest palindrome possible from there (in most cases, it will be 1 or 2 chars). There's no need to consider longer substrings centred on that position once you have a failing case, so that eliminates much of the unnecessary work we're doing here.



          Hint: for this we can use std::make_reverse_iterator() and std::mismatch().




          Finally, the single test we have in main() isn't really enough. At a minimum, we want examples of odd- and even-length palindromes, and also check that we handle the trivial case of empty string as input.






          share|improve this answer






















          • Perhaps an unnamed namespace would be more idiomatic C++ than using the static keyword.
            – user673679
            24 mins ago










          • Yes, agreed. The effect is pretty much the same. I've edited to the more idiomatic form.
            – Toby Speight
            23 mins ago


















          up vote
          1
          down vote













          I suppose that a little optimization could be done by changing the way the substrings are extracted from the main string: the iterations should start from the original string itself and then continue by subtracting characters.



          In this way the first time isPalindrome() returns true, the palindrome is the longest one.



          Here is a little edit to your longestPalindrome function:



          int longestPalindrome(std::string& str, std::string& palindromeStr)

          for (int len = str.length(); len > 1; len--) // One-char strings can't be considered as palindromes...

          for (int j = 0; j <= str.length() - len; j++)

          std::string sub = str.substr(j, j + len);
          if (isPalindrome(sub))

          palindromeStr = sub;
          return len;



          return 0; // It is not a palindrome...






          share|improve this answer






















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f203983%2ffind-longest-palindrome-substring%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            4
            down vote













            The code is reasonably clear and obvious, but has some severe inefficiencies.



            First, let's pick up some simple oversights. Both isPalindrome() and longestPalindrome() ought to have internal linkage (either using the static keyword, or in the anonymous namespace), and the str arguments should be reference to const:



            namespace 

            bool isPalindrome(const std::string& str)




             int longestPalindrome(const std::string& str, std::string& palindromeStr)







            The next oversight is that std::string::length() returns a std::size_t, so don't compare it with (signed) int:



            for (std::size_t i = 0, j = str.length()-1; i<j; ++i, --j)
            // ^^^^^^^^^^^


            Note that I've left a bug there (that's neatly missed because we always call this with a non-empty string): if str.length() is zero, then j starts at a very large positive value (because the subtraction is unsigned, and wraps).



            BTW, there's a neat way to test a string for symmetry (at the expense of repeating the initial comparisons), using <algorithm>:



            static bool isPalindrome(const std::string& str)

            return std::equal(str.begin(), str.end(), str.rbegin());




            Now to the matter of efficiency. We're creating new string objects for every possible substring of the input. That's a lot of copying. We could reduce that by using std::string_view.



            That's only part of the way towards an efficient solution, though. We really need to change the algorithm. My recommendation is to iterate over each character as a possible mid-point of an embedded palindrome, and at each position, determine what's the longest palindrome possible from there (in most cases, it will be 1 or 2 chars). There's no need to consider longer substrings centred on that position once you have a failing case, so that eliminates much of the unnecessary work we're doing here.



            Hint: for this we can use std::make_reverse_iterator() and std::mismatch().




            Finally, the single test we have in main() isn't really enough. At a minimum, we want examples of odd- and even-length palindromes, and also check that we handle the trivial case of empty string as input.






            share|improve this answer






















            • Perhaps an unnamed namespace would be more idiomatic C++ than using the static keyword.
              – user673679
              24 mins ago










            • Yes, agreed. The effect is pretty much the same. I've edited to the more idiomatic form.
              – Toby Speight
              23 mins ago















            up vote
            4
            down vote













            The code is reasonably clear and obvious, but has some severe inefficiencies.



            First, let's pick up some simple oversights. Both isPalindrome() and longestPalindrome() ought to have internal linkage (either using the static keyword, or in the anonymous namespace), and the str arguments should be reference to const:



            namespace 

            bool isPalindrome(const std::string& str)




             int longestPalindrome(const std::string& str, std::string& palindromeStr)







            The next oversight is that std::string::length() returns a std::size_t, so don't compare it with (signed) int:



            for (std::size_t i = 0, j = str.length()-1; i<j; ++i, --j)
            // ^^^^^^^^^^^


            Note that I've left a bug there (that's neatly missed because we always call this with a non-empty string): if str.length() is zero, then j starts at a very large positive value (because the subtraction is unsigned, and wraps).



            BTW, there's a neat way to test a string for symmetry (at the expense of repeating the initial comparisons), using <algorithm>:



            static bool isPalindrome(const std::string& str)

            return std::equal(str.begin(), str.end(), str.rbegin());




            Now to the matter of efficiency. We're creating new string objects for every possible substring of the input. That's a lot of copying. We could reduce that by using std::string_view.



            That's only part of the way towards an efficient solution, though. We really need to change the algorithm. My recommendation is to iterate over each character as a possible mid-point of an embedded palindrome, and at each position, determine what's the longest palindrome possible from there (in most cases, it will be 1 or 2 chars). There's no need to consider longer substrings centred on that position once you have a failing case, so that eliminates much of the unnecessary work we're doing here.



            Hint: for this we can use std::make_reverse_iterator() and std::mismatch().




            Finally, the single test we have in main() isn't really enough. At a minimum, we want examples of odd- and even-length palindromes, and also check that we handle the trivial case of empty string as input.






            share|improve this answer






















            • Perhaps an unnamed namespace would be more idiomatic C++ than using the static keyword.
              – user673679
              24 mins ago










            • Yes, agreed. The effect is pretty much the same. I've edited to the more idiomatic form.
              – Toby Speight
              23 mins ago













            up vote
            4
            down vote










            up vote
            4
            down vote









            The code is reasonably clear and obvious, but has some severe inefficiencies.



            First, let's pick up some simple oversights. Both isPalindrome() and longestPalindrome() ought to have internal linkage (either using the static keyword, or in the anonymous namespace), and the str arguments should be reference to const:



            namespace 

            bool isPalindrome(const std::string& str)




             int longestPalindrome(const std::string& str, std::string& palindromeStr)







            The next oversight is that std::string::length() returns a std::size_t, so don't compare it with (signed) int:



            for (std::size_t i = 0, j = str.length()-1; i<j; ++i, --j)
            // ^^^^^^^^^^^


            Note that I've left a bug there (that's neatly missed because we always call this with a non-empty string): if str.length() is zero, then j starts at a very large positive value (because the subtraction is unsigned, and wraps).



            BTW, there's a neat way to test a string for symmetry (at the expense of repeating the initial comparisons), using <algorithm>:



            static bool isPalindrome(const std::string& str)

            return std::equal(str.begin(), str.end(), str.rbegin());




            Now to the matter of efficiency. We're creating new string objects for every possible substring of the input. That's a lot of copying. We could reduce that by using std::string_view.



            That's only part of the way towards an efficient solution, though. We really need to change the algorithm. My recommendation is to iterate over each character as a possible mid-point of an embedded palindrome, and at each position, determine what's the longest palindrome possible from there (in most cases, it will be 1 or 2 chars). There's no need to consider longer substrings centred on that position once you have a failing case, so that eliminates much of the unnecessary work we're doing here.



            Hint: for this we can use std::make_reverse_iterator() and std::mismatch().




            Finally, the single test we have in main() isn't really enough. At a minimum, we want examples of odd- and even-length palindromes, and also check that we handle the trivial case of empty string as input.






            share|improve this answer














            The code is reasonably clear and obvious, but has some severe inefficiencies.



            First, let's pick up some simple oversights. Both isPalindrome() and longestPalindrome() ought to have internal linkage (either using the static keyword, or in the anonymous namespace), and the str arguments should be reference to const:



            namespace 

            bool isPalindrome(const std::string& str)




             int longestPalindrome(const std::string& str, std::string& palindromeStr)







            The next oversight is that std::string::length() returns a std::size_t, so don't compare it with (signed) int:



            for (std::size_t i = 0, j = str.length()-1; i<j; ++i, --j)
            // ^^^^^^^^^^^


            Note that I've left a bug there (that's neatly missed because we always call this with a non-empty string): if str.length() is zero, then j starts at a very large positive value (because the subtraction is unsigned, and wraps).



            BTW, there's a neat way to test a string for symmetry (at the expense of repeating the initial comparisons), using <algorithm>:



            static bool isPalindrome(const std::string& str)

            return std::equal(str.begin(), str.end(), str.rbegin());




            Now to the matter of efficiency. We're creating new string objects for every possible substring of the input. That's a lot of copying. We could reduce that by using std::string_view.



            That's only part of the way towards an efficient solution, though. We really need to change the algorithm. My recommendation is to iterate over each character as a possible mid-point of an embedded palindrome, and at each position, determine what's the longest palindrome possible from there (in most cases, it will be 1 or 2 chars). There's no need to consider longer substrings centred on that position once you have a failing case, so that eliminates much of the unnecessary work we're doing here.



            Hint: for this we can use std::make_reverse_iterator() and std::mismatch().




            Finally, the single test we have in main() isn't really enough. At a minimum, we want examples of odd- and even-length palindromes, and also check that we handle the trivial case of empty string as input.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 22 mins ago

























            answered 37 mins ago









            Toby Speight

            19.1k43697




            19.1k43697











            • Perhaps an unnamed namespace would be more idiomatic C++ than using the static keyword.
              – user673679
              24 mins ago










            • Yes, agreed. The effect is pretty much the same. I've edited to the more idiomatic form.
              – Toby Speight
              23 mins ago

















            • Perhaps an unnamed namespace would be more idiomatic C++ than using the static keyword.
              – user673679
              24 mins ago










            • Yes, agreed. The effect is pretty much the same. I've edited to the more idiomatic form.
              – Toby Speight
              23 mins ago
















            Perhaps an unnamed namespace would be more idiomatic C++ than using the static keyword.
            – user673679
            24 mins ago




            Perhaps an unnamed namespace would be more idiomatic C++ than using the static keyword.
            – user673679
            24 mins ago












            Yes, agreed. The effect is pretty much the same. I've edited to the more idiomatic form.
            – Toby Speight
            23 mins ago





            Yes, agreed. The effect is pretty much the same. I've edited to the more idiomatic form.
            – Toby Speight
            23 mins ago













            up vote
            1
            down vote













            I suppose that a little optimization could be done by changing the way the substrings are extracted from the main string: the iterations should start from the original string itself and then continue by subtracting characters.



            In this way the first time isPalindrome() returns true, the palindrome is the longest one.



            Here is a little edit to your longestPalindrome function:



            int longestPalindrome(std::string& str, std::string& palindromeStr)

            for (int len = str.length(); len > 1; len--) // One-char strings can't be considered as palindromes...

            for (int j = 0; j <= str.length() - len; j++)

            std::string sub = str.substr(j, j + len);
            if (isPalindrome(sub))

            palindromeStr = sub;
            return len;



            return 0; // It is not a palindrome...






            share|improve this answer


























              up vote
              1
              down vote













              I suppose that a little optimization could be done by changing the way the substrings are extracted from the main string: the iterations should start from the original string itself and then continue by subtracting characters.



              In this way the first time isPalindrome() returns true, the palindrome is the longest one.



              Here is a little edit to your longestPalindrome function:



              int longestPalindrome(std::string& str, std::string& palindromeStr)

              for (int len = str.length(); len > 1; len--) // One-char strings can't be considered as palindromes...

              for (int j = 0; j <= str.length() - len; j++)

              std::string sub = str.substr(j, j + len);
              if (isPalindrome(sub))

              palindromeStr = sub;
              return len;



              return 0; // It is not a palindrome...






              share|improve this answer
























                up vote
                1
                down vote










                up vote
                1
                down vote









                I suppose that a little optimization could be done by changing the way the substrings are extracted from the main string: the iterations should start from the original string itself and then continue by subtracting characters.



                In this way the first time isPalindrome() returns true, the palindrome is the longest one.



                Here is a little edit to your longestPalindrome function:



                int longestPalindrome(std::string& str, std::string& palindromeStr)

                for (int len = str.length(); len > 1; len--) // One-char strings can't be considered as palindromes...

                for (int j = 0; j <= str.length() - len; j++)

                std::string sub = str.substr(j, j + len);
                if (isPalindrome(sub))

                palindromeStr = sub;
                return len;



                return 0; // It is not a palindrome...






                share|improve this answer














                I suppose that a little optimization could be done by changing the way the substrings are extracted from the main string: the iterations should start from the original string itself and then continue by subtracting characters.



                In this way the first time isPalindrome() returns true, the palindrome is the longest one.



                Here is a little edit to your longestPalindrome function:



                int longestPalindrome(std::string& str, std::string& palindromeStr)

                for (int len = str.length(); len > 1; len--) // One-char strings can't be considered as palindromes...

                for (int j = 0; j <= str.length() - len; j++)

                std::string sub = str.substr(j, j + len);
                if (isPalindrome(sub))

                palindromeStr = sub;
                return len;



                return 0; // It is not a palindrome...







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 26 mins ago

























                answered 45 mins ago









                rudicangiotti

                1366




                1366



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f203983%2ffind-longest-palindrome-substring%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    What does second last employer means? [closed]

                    List of Gilmore Girls characters

                    Confectionery