文字カウントテクニック - tanakakenji/Rinko GitHub Wiki
文字列内の文字の頻度をカウントすることは、多くの文字列処理タスクで重要です。ここでは、C++を使用してこのテクニックを実装する方法を説明します。
最も一般的なアプローチは、ハッシュテーブル(C++ではstd::unordered_map
)を使用することです。
#include <iostream>
#include <string>
#include <unordered_map>
std::unordered_map<char, int> countCharacters(const std::string& str) {
std::unordered_map<char, int> charCount;
for (char c : str) {
charCount[c]++;
}
return charCount;
}
int main() {
std::string text = "hello world";
auto frequencyMap = countCharacters(text);
for (const auto& pair : frequencyMap) {
std::cout << "'" << pair.first << "': " << pair.second << std::endl;
}
return 0;
}
この例では、countCharacters
関数が文字列内の各文字の出現回数をカウントし、結果をunordered_map
として返します。
出力:
'h': 1
'e': 1
'l': 3
'o': 2
' ': 1
'w': 1
'r': 1
'd': 1
問題が小文字のラテン文字(a-z)のみに限定されている場合、固定サイズの配列を使用することで、より効率的に実装できます。
#include <iostream>
#include <string>
#include <array>
std::array<int, 26> countLowercaseLetters(const std::string& str) {
std::array<int, 26> charCount = {0};
for (char c : str) {
if (c >= 'a' && c <= 'z') {
charCount[c - 'a']++;
}
}
return charCount;
}
int main() {
std::string text = "helloworld";
auto frequencyArray = countLowercaseLetters(text);
for (int i = 0; i < 26; i++) {
if (frequencyArray[i] > 0) {
std::cout << "'" << char('a' + i) << "': " << frequencyArray[i] << std::endl;
}
}
return 0;
}
この方法では、26の要素を持つ固定サイズの配列を使用しています。各インデックスは特定のアルファベットに対応します(0 = 'a', 1 = 'b', など)。
出力:
'd': 1
'e': 1
'h': 1
'l': 3
'o': 2
'r': 1
'w': 1
重要な点として、文字カウンターの空間複雑度は多くの場合O(1)です。これは、カウントする文字の種類が固定されているためです。
- ラテン小文字のみの場合:26文字
- ASCII文字の場合:128文字
- 拡張ASCII文字の場合:256文字
これらの場合、入力文字列の長さ(n)に関係なく、カウンターのサイズは一定です。そのため、空間複雑度はO(1)となります。
ただし、Unicode文字など、文字の範囲が非常に大きい場合は、この限りではありません。そのような場合、空間複雑度は文字の種類の数に依存し、O(k)となります(kは一意な文字の数)。
- 一般的な場合は
std::unordered_map
を使用すると柔軟性が高く、様々な文字に対応できます。 - 小文字のラテン文字のみを扱う場合は、固定サイズの配列を使用すると効率的です。
- 多くの場合、文字カウンターの空間複雑度はO(1)です。これは、カウントする文字の種類が固定されているためです。
これらのテクニックを適切に使用することで、効率的で正確な文字カウントを実装することができます。問題の制約条件をよく理解し、適切な方法を選択することが重要です。