実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 180
問題概要
個の、英小文字からなる文字列 []tex: S_1, S_2, \cdots, S_N] が与えらえる。これらの文字列の長さの最大値を とする。以下の条件を満たす 個の文字列 を出力せよ。
- 条件 :
- 各 は英小文字か
*
からなる。 - 各 の末尾は
*
ではない。 - 各 について、
- 各 について、 の 文字目を の昇順に連結したものは と一致する。
- 各 について、 の 文字目は存在しないか
*
である。
- 各 は英小文字か
制約
- は整数で、 を満たす。
考察
やりたいこととしては、「横書きの文字列を縦書きにして出力する」ということで、つらつらと書かれた条件はそのためのものである。
基本的には条件の通りに2重ループを用いてそのまま実装していけばよいのだが、少し詰まるのは条件2「各 の末尾は*
ではない」というところ。どう実装しようか少し迷ったが、文字列に対してもpop_back()
が使えることを利用して、「 が空文字列でないかつ末尾が*
である限り末尾を削除する」という方針で書くことにした。
C++ の string
に関する扱いはこの記事が詳しいので参照のこと。
コード
#include <bits/stdc++.h> using namespace std; #define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++) #define rrep(i, start, end) for (auto i = (start); (i) >= (end); (i)--) template <typename T> inline bool chmax(T &a, T b) { return ((a < b) ? (a = b, true) : (false)); } // ======================================== // int main() { int N; cin >> N; vector<string> S(N); rep(i, 0, N) cin >> S[i]; int M = 0; rep(i, 0, N) chmax(M, (int)S[i].length()); rep(i, 0, M) { string t; for (int j = N - 1; j >= 0; --j) { if (i < S[j].length()) t += S[j][i]; else t += '*'; } while (!t.empty() && t.back() == '*') { t.pop_back(); } cout << t << endl; } }
実装時間: 30分
条件の通りにそのまま実装すれば良いということに気づくのに時間かかった...