This is my attempt at answering "Palindrome from all the substrings" which asks to detect if a string contains a palindrome as a substring.
The algorithm implemented here is the one described in its accepted answer.
First, here is the main function (based on the corresponding main in the initial question):
int main()
{
size_t n_str;
std::cin >> n_str;
for (size_t i = 0; i < n_str; ++i)
{
std::string str;
std::cin >> str;
std::cout << (contains_palindrome(str) ? "YES" : "NO") << std::endl;
}
return EXIT_SUCCESS;
}
Second, I decided to extend contains_palindrome from exclusively accepting an std::string to taking any container (e.g. std::vector<char>, std::array<int,N>, ...) as an argument:
template <class T>
bool contains_palindrome(const T& s)
{
if (s.size() < 2) return false;
for (auto it = s.cbegin(),
next = std::next(it),
nnext = std::next(next);
nnext != s.cend();
it = next, next = nnext, std::advance(nnext, 1))
if (*it == *next || *it == *nnext)
return true;
return *std::prev(s.cend()) == *std::prev(s.cend(), 2);
}
NB: <cstdlib>, <iostream>, <iterator> and <string> are required.
QUESTION(S):
Is there any instance of bad practice in the code? In particular,
- is the
templatecorrect according to the desired behaviour? Am I right in assuming thatcontains_palindromewill work as expected on any class implementing the methodssize(),cbegin()andcend()? - is the use of iterators done correctly? In particular, I made sure to
call the "
cversions" ofbegin()andend()(after declaringsasconst) and usedstd::prev(it),std::next(it)andstd::advance(it,1)instead of, respectively,it-1,it+1andit++: is this, as I was told, good practice? Are there other instances of good practice related to iterators that I overlooked? I used iterators because I learned that it is "the [right] way to do it in C++" but what do I gain over the following C-like approach?
for (size_t i = 0; i < s.size()-2; ++i) if (s[i] == s[i+1] || s[i] == s[i+2]) return true; return s[s.size()-1] == s[s.size()-2];