回文部分文字列の最大長がkを超えない文字列を生成するC++プログラム
問題の概要
2つの整数 n と k が与えられたとします。ここで、'a'、'b'、'c' の3種類の文字のみを使用して長さ n の文字列 S を生成することを考えます。ただし、S に含まれる回文となっている部分文字列の最大の長さは、k を超えてはいけません。
例えば、入力が n = 3、k = 2 の場合、出力は "aab" となります。文字列の長さは3であり、長さ2の回文部分文字列 "aa" を含んでいるためです(他の答えも存在します)。
解法のアプローチ
この問題は実は非常にシンプルに解くことができます。'a'、'b'、'c' の3文字をこの順番で繰り返す文字列(例: "abcabc...")を生成すればよいのです。
このような文字列では、隣り合う2文字が同じになることはなく、1文字を挟んで同じ文字が現れることもありません。そのため、長さ2以上の回文部分文字列は一切存在せず、回文部分文字列の最大長は常に1になります。したがって、k が1以上である限り、この方法で常に条件を満たす文字列を生成できます。
手順
この問題を解くために、以下の手順に従います。
S := 空文字列
j := 0
i := 0 から i < n まで、i を1ずつ増やしながら繰り返す:
S := S に (j + 'a' のASCIIコード) で表される文字を連結
j := (j + 1) mod 3
S を返す
C++での実装例
理解を深めるために、以下の実装例を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
string solve(int n, int k) {
string S = "";
int j = 0;
for (int i = 0; i < n; i++) {
S += j + 'a';
j = (j + 1) % 3;
}
return S;
}
int main() {
int n = 3;
int k = 2;
cout << solve(n, k) << endl;
}
入力
3, 2
出力
abc
出力の解説
出力された "abc" は長さ3の文字列で、回文となっている部分文字列は "a"、"b"、"c" の長さ1のものだけです。回文部分文字列の最大長は1であり、これは k = 2 を超えていないため、条件を満たす正解の一つとなっています。
このアルゴリズムの計算量は文字列の生成に O(n)、使用する記憶域も O(n) であり、非常に効率的です。
-
Pythonで解く:m種類の文字から作る長さnの回文を含まない文字列の個数を求める方法
問題の概要 m種類の文字と整数nが与えられたとき、これらの文字を使って構成できる「長さ2以上の回文(前から読んでも後ろから読んでも同じになる文字列)を部分文字列として含まない」長さnの文字列の個数を求める問題です。答えが非常に大きな値になる可能性があるため、109+7で割った余りを返します。 具体例で理解する 例として、n = 2、m = 3 のケースを見てみましょう。使用できる文字が {x, y, z} の3種類であるとき、理論上は [xx, xy, xz, yx, yy, yz, zx, zy, zz] の9通りの文字列が作れます。しかし、このうち [xx, yy, zz] は同じ文字が
-
Pythonで文字列内に2回以上出現する最長部分文字列の長さを求めるプログラム
小文字のみで構成された文字列 s が与えられたとき、s の中に少なくとも2回以上出現する最長の部分文字列の長さを求めます。そのような部分文字列が存在しない場合は 0 を返します。たとえば、入力が s = abdgoalputabdtypeabd の場合、2回以上出現する最長の部分文字列は abd なので、出力は 3 になります。解法のアプローチ:接尾辞(サフィックス)の活用この問題は「接尾辞」という考え方を使うとスマートに解けます。文字列に2回以上現れる部分文字列は、必ず開始位置の異なる2つの接尾辞の共通接頭辞として現れます。そこで、すべての接尾辞を辞書順にソートすれば、似た接尾辞どうしが隣り