[AtCoder]ABC 054B – Template Matching[C++]

プログラミング

AtCoderの過去問をC++で解いていきます。今回は、ABC 054B – Template Matchingだけです。B問題に入ってから、一日に複数問、解くのが難しくなってきました。

ABC 054B – Template Matching

問題

縦N行、横N列に画素が並んだ画像Aと、縦M行、横M列に画素が並んだテンプレート画像Bが与えられます。
画素は画像を構成する最小単位であり、ここでは1×1の正方形とします。
また、与えられる画像は全て2値画像であり、各画素の色は白と黒の2種類で表されます。
入力において、全ての画素は文字で表されており、.は白色の画素、 # は黒色の画素に対応します。
画像AはN個の文字列A1,…,ANで表されます。
文字列Aiのj文字目は、画像Aの上からi番目、左からj番目の画素に対応します。(1≦i,j≦N)
同様に、テンプレート画像BはM個の文字列B1,…,BMで表されます。
文字列Biのj文字目は、テンプレート画像Bの上からi番目、左からj番目の画素に対応します。(1≦i,j≦M)
画像の平行移動のみ許されるとき、テンプレート画像Bが画像Aの中に含まれているかを判定してください。

自分の回答

#include <bits/stdc++.h>
using namespace std;
int main () {
  int N, M;
  cin >> N >> M;
  string A[N],B[M];
  // 入力の受付
  for(int i = 0; i < N; i++){
    cin >> A[i];
  } 
  for(int i = 0; i < M; i++){
    cin >> B[i];
  }
  // bool型の宣言
  bool ans = false;
  // 一行ずつ取り出して、一致しているか判断
  for(int i = 0; i <= N - M; i++){
    for(int j = 0; j <= N - M; j++){
      int cnt = 0;
      for(int k = 0; k < M; k++){
        if(B[k] == A[i + k].substr(j,M)){
          cnt++;
        }
      }
      if(cnt == M) {
        ans = true;
        break;
      }
    }
    if(ans){
      break;
    }
  }
  // 出力
  if(ans){
    cout << "Yes" << endl;
  }
  else{
    cout << "No" << endl;
  }
}

難しすぎでは?色々新しい要素が出てきました。
入力を受け付けた後、15行目でbool型で変数ansを宣言しています。真か偽かのみを格納するのなら、bool型が適しています。
次に、for文を使って一行一行取り出してきます。forの範囲をN-Mとしているのは、例えば、画像Aの一番下の行が、2行以上あるテンプレート画像Bと一致しても確かめるまでもなく、一致しないことがわかっているからです。
20行目から始まるfor文で取り出した行内で、substr関数を使って文字列を切り出して、一致しているか確認しています。もし、文字列が一致したら、変数cntの値が増えていきます。もし、cntとテンプレートの行数Mの値が等しければ、テンプレートが完全に一致したことを示すので、ansをtrueとします。

bool型
真か偽の格納のみを目的として変数を作成する際にはbool型が適しています。

substr関数
部分文字列を取得します。
変数.substr(pos,n)という形で使い、pos番目からn要素の文字列を返します。

string s = "abcdefgh";

cout << s.substr(0,2) << endl;  => "ab"
cout << s.substr(2,3) << endl;  => "cde"
タイトルとURLをコピーしました