Search on the blog

2011年9月22日木曜日

文字列に関するcoding tips

ちょっとしたtipsを紹介します。
  1. accumulate()で文字結合
  2. mapは使わない
  3. 文字をint型に代入する
まず、1.番目。vectorで与えられた入力をconcatenate して新しい文字列を作成せよ。よくありますね。これをどう書くか。

vector<string> x;

void init() {
    x.push_back("acchan");
    x.push_back("yuko");
    x.push_back("yukirin");
    x.push_back("mayuyu");
}

int main() {
    init();

    string y = "";
    REP(i, x.size())
        y += x[i];

    cout << y << endl;
    return 0;
}

でもいいけど、accumulate()を使うとちょっとだけかっこよく書けます。accumulate()はdefaultでは演算子+を用いる。stringに対する+は文字の結合なのでそのまま使えます。

int main() {
    init();

    string y = accumulate(ALL(x), string());

    cout << y << endl;
    return 0;
}


次に、2.番目。文字の出現回数を数えています。char -> intへの写像なので、mapを使うのが自然に見えます。

int main() {
    string x = "riverponiiteerutoshushuheavyrotationeverydaykachusha";

    map<char, int> cnt;
    REP(i, x.size())
        cnt[x[i]]++;
}

でも、charなんて高々[0, 256)までなので、配列に入れるのもありです。C++の配列はランダムアクセスなので、こっちの方が計算量は安いです。[0, 256)と書きましたが、ASCIIコード表を見ると、実際に使われるコードは[0, 128)で十分のようです。AKBのメンバーの名前を覚える暇があったら、ASCIIコードを覚えましょう。(→自分)

int main() {
    string x = "riverponiiteerutoshushuheavyrotationeverydaykachusha";

    int cnt[128];
    memset(cnt, 0, sizeof(cnt));
    REP(i, x.size())
        cnt[x[i]]++;
}

最後に、3.番目。これは、文字をインクリメントして走査したい場合です。それぞれの数字がdigit中に何回出てくるかを標準出力に表示します。

int main() {
    string digit = "1234254723075027659279743057423953";

    for (char i = '0'; i <= '9'; i++)
        cout << count(ALL(digit), i) << endl;
}

とか、

int main() {
    string digit = "1234254723075027659279743057423953";

    REP(i, 10)
        cout << count(ALL(digit), i+'0') << endl;
}

とかやっていましたが、以下のようにできますね。プロコン界伝統の悪しきマクロで書いてますが、iはintで持っています。charではなく、intで持っていた方が何かと便利です。

int main() {
    string digit = "1234254723075027659279743057423953";

    FOR (i, '0', '9'+1)
        cout << count(ALL(digit), i) << endl;
}

0 件のコメント:

コメントを投稿