C++ で文字列が回文かどうかをチェックする
- 
          
            C++ で文字列の回文をチェックするには rbegin/rendメソッドを用いてstringのコピーコンストラクタを使用する
- 
          
            C++ で文字列の回文をチェックするには std::equalメソッドを使用する
- カスタム関数を使って C++ で文字列の回文をチェックする
 
この記事では、C++ で文字列が回文かどうかをチェックする方法をいくつか説明します。
C++ で文字列の回文をチェックするには rbegin/rend メソッドを用いて string のコピーコンストラクタを使用する
    
string クラスオブジェクトは演算子 == を用いた比較をサポートしており、回文パターンに適合する文字列を見つけるために利用することができます。回文は文字を逆順にマッチさせることを意味するので、rbegin と rend のイテレータを用いて新しい文字列オブジェクトを構築する必要があります。残りの部分は必要に応じて if 文の中で構築することになります。
次の例では、2つの文字列、すなわち 1 単語の回文と複数単語の回文を宣言しています。スペースを含む文字列は定義パターンに合致しますが、このメソッドは回文として検出できないことに注意してください。
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::equal;
using std::remove;
using std::string;
int main() {
  string s1 = "radar";
  string s2 = "Was it a cat I saw";
  if (s1 == string(s1.rbegin(), s1.rend())) {
    cout << "s1 is a palindrome" << endl;
  } else {
    cout << "s1 is not a palindrome" << endl;
  }
  if (s2 == string(s2.rbegin(), s2.rend())) {
    cout << "s2 is a palindrome" << endl;
  } else {
    cout << "s2 is not a palindrome" << endl;
  }
  return EXIT_SUCCESS;
}
出力:
s1 is a palindrome
s2 is not a palindrome
C++ で文字列の回文をチェックするには std::equal メソッドを使用する
最後の実装はワンワード文字列でも動作しますが、オブジェクトのコピーを作成してその全範囲を比較するというオーバーヘッドを伴います。同じ string オブジェクト範囲の前半と後半を比較するには、std::equal アルゴリズムを利用することができます。std::equal は、与えられた 2つの範囲の要素が等しい場合、ブール値 true を返します。この関数は 2つ目の範囲については 1つのイテレータ s1.rbegin() を取るだけであることに注意してください。
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::equal;
using std::remove;
using std::string;
int main() {
  string s1 = "radar";
  string s2 = "Was it a cat I saw";
  equal(s1.begin(), s1.begin() + s1.size() / 2, s1.rbegin())
      ? cout << "s1 is a palindrome" << endl
      : cout << "s1 is not a palindrome" << endl;
  equal(s2.begin(), s2.begin() + s2.size() / 2, s2.rbegin())
      ? cout << "s2 is a palindrome" << endl
      : cout << "s2 is not a palindrome" << endl;
  return EXIT_SUCCESS;
}
出力:
s1 is a palindrome
s2 is not a palindrome
カスタム関数を使って C++ で文字列の回文をチェックする
これまでのメソッドでは、複数の単語を含む文字列では不足していましたが、カスタム関数を実装することで解決することができます。この例では、ブール値関数 checkPalindrome を用いて string& 引数を受け取り、その値をローカルの string 変数に格納しています。次に、このローカルオブジェクトは transform アルゴリズムで処理されて小文字に変換され、結果として erase-remove イディオムで空白文字をすべて削除します。最後に、if 文の条件で equal アルゴリズムを呼び出し、対応するブール値を返します。ただし、このメソッドは文字列がマルチバイト文字で構成されている場合に失敗することに注意してください。したがって、小文字変換メソッドは、すべての一般的な文字エンコーディングスキームをサポートするように実装されている必要があります。
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::equal;
using std::remove;
using std::string;
bool checkPalindrome(string& s) {
  string tmp = s;
  transform(tmp.begin(), tmp.end(), tmp.begin(),
            [](unsigned char c) { return tolower(c); });
  tmp.erase(remove(tmp.begin(), tmp.end(), ' '), tmp.end());
  if (equal(tmp.begin(), tmp.begin() + tmp.size() / 2, tmp.rbegin())) {
    return true;
  } else {
    return false;
  }
}
int main() {
  string s1 = "radar";
  string s2 = "Was it a cat I saw";
  checkPalindrome(s1) ? cout << "s1 is a palindrome" << endl
                      : cout << "s1 is not a palindrome" << endl;
  checkPalindrome(s2) ? cout << "s2 is a palindrome" << endl
                      : cout << "s2 is not a palindrome" << endl;
  return EXIT_SUCCESS;
}
出力:
s1 is a palindrome
s2 is a palindrome
