C++で文字列から一部の文字を削除して辞書内の最長の単語を見つける方法
問題の概要
辞書と文字列 s が与えられたとします。このとき、文字列 s から一部の文字を削除(つまり残りの文字の順序を保ったまま)することで作成できる、辞書内の最長の単語を見つけるのが目的です。
例えば、文字列 s が "apbreoigroakml" で、辞書が {"prog", "ram", "program"} の場合、答えは "program" になります。これは "program" の各文字が s に順番どおりに現れている(部分列となっている)ためです。
解決のアプローチ
この問題を解くには、次の手順で進めます。
まず、辞書内のすべての単語を走査します。次に、各単語について「その単語が与えられた文字列 s の部分列であるか」を判定します。部分列である単語の中で最も長いものを結果として返せばよいのです。
部分列の判定方法
部分列の判定は、2つのインデックスを使った貪欲法で効率的に行えます。文字列 s を先頭から順に走査しながら、判定対象の単語の文字と一致するたびに単語側のインデックスを進めます。最終的に単語のすべての文字が一致していれば、その単語は s の部分列であると判断できます。
アルゴリズムの手順
1. 結果を格納する文字列を空文字列で初期化します。
2. 辞書内の各単語について、現在の結果より長い場合にのみ部分列判定を行います(不要な計算を省くため)。
3. 単語が s の部分列であれば、結果とその長さを更新します。
4. すべての単語を確認した後、結果を返します。
C++での実装例
#include<iostream>
#include<vector>
using namespace std;
bool isSubSequence(string s1, string s2) {
int m = s1.length(), n = s2.length();
int j = 0;
for (int i=0; i<n&&j<m; i++)
if (s1[j] == s2[i])
j++;
return (j==m);
}
string getLongestSubstr(vector <string > dict, string s) {
string result = "";
int length = 0;
for (string word : dict) {
if (length < word.length() && isSubSequence(word, s)) {
result = word;
length = word.length();
}
}
return result;
}
int main() {
vector <string > dict = {"prog", "ram", "program"};
string str = "apbreoigroakml" ;
cout << getLongestSubstr(dict, str) << endl;
}出力
program
計算量について
辞書内の単語数を D、文字列 s の長さを N とすると、各単語の部分列判定は O(N) で行えるため、全体の時間計算量は O(D × N) となります。空間計算量は O(1) で、追加のメモリはほとんど必要ありません。
-
【C++】2つの文字列を比較して共通しない文字を抽出するプログラム
この記事では、2つの異なる文字列を比較した際に、共通しない文字(どちらか一方にしか存在しない文字)を見つけ出すプログラムについて解説します。 ご存知の通り、文字列とは本質的に文字の配列です。そのため、比較を行う際は、一方の文字列の文字を先頭から順に走査しながら、その文字がもう一方の文字列にも存在するかどうかを確認していきます。 ここで、最初の文字列をA、2番目の文字列をBとすると、まず「A − B」(Aには含まれるがBには含まれない文字)が求められます。同様の手順で「B − A」も計算できます。 この2つの結果を組み合わせると、次の式になります。 ( A − B ) ∪ ( B − A )
-
C++で文字列の順列の総数を求めるプログラムの作成方法
文字列に含まれる文字は、さまざまな順序で並べ替えることができます。本記事では、与えられた文字列から作成できる順列の数を求める方法を解説します。たとえば「abc」という3文字の文字列の場合、並べ方は 3! = 6 通りあります。つまり、n 文字の文字列であれば、最大で n! 通りの並べ方が存在します。しかし、「aab」のように同じ文字が複数回含まれている場合、単純に 6 通りにはなりません。「aab」の全パターンを書き出してみると、次のようになります。abaaabbaabaaaababaこのうち、(1番目と6番目)、(2番目と5番目)、(3番目と4番目) のペアはそれぞれ同一の並び方です。したが