サブストリングとしてYを含まないストリングXで最長のサブシーケンスを見つける動的プログラミングアルゴリズムはありますか?この問題は、最長の共通サブシーケンスや文字列など、他のDP文字列アルゴリズムと非常に似ているように見えます。オーバーラップするYの発生を処理できる必要があります。
これは2状態のDP問題である可能性があります。状態[s_pos、t_pos]は、文字列S [pos _ .. M]を部分文字列として持たないs_posで始まる文字列Sの最も長い部分列です。 Nは文字列Sの長さで、Mは文字列Tの長さです。ただし、私の遷移は正しくありません。S= aaabc
およびT = aabc
の場合は取得されません。問題はelseステートメントにあります-文字が等しい場合に遷移する方法がわかりません。 実際には、ifブランチが間違っていると感じています...誰かが間違っている可能性を知っていますか?
S = aaab
およびT = aab
の場合も失敗します。失敗する理由を説明できます。solve(0、0)を呼び出すと仮定します。 solve(0、0)はsolve(1、1)を呼び出します。 solve(1、1)はsolve(2、2)を呼び出します。 s [2]!= t [2]なので、solve(3、0)から検索を再開します。ただし、aabは部分文字列であり、これをチェックしたり、このケースを考慮したりすることはありません...
int solve(int s_pos, int t_pos)
{
if (s_pos >= N || t_pos >= M) return 0;
if (t_pos == M - 1 && s[s_pos] == t[t_pos]) return 0;
int ret = 0;
if (s[s_pos] != t[t_pos])
{
int tmp = solve(s_pos + 1, 0);
ret = max(ret, tmp + 1);
}
else
{
for (int i = s_pos + 1; i < N; i++)
{
int tmp = solve(i, t_pos + 1);
if (tmp != 0)
{
ret = max(ret, 1 + tmp);
}
}
}
return ret;
}
これでうまくいくはずです。私はそれをベーシックに似たメタコードで書いた。
LONGEST = ""
while N>0
POS = find(T,S)
if POS>0 then
SUB = left(S,POS)
else
SUB = S
POS = N
endif
if len(SUB) > len(LONGEST) then
LONGEST = SUB
endif
N = N-POS
wend
主な問題は、elseステートメント内のforループであり、関数を再帰的に呼び出すことです。
再帰または反復のいずれかのアプローチを選択しますが、それらを混合することは間違っているようです。
私は反復的なアプローチで行きます。
関数の外に空のリストを作成します。
次にsolve
を呼び出します。
この関数でこのアプローチを試してください:
文字列をループします。現在の文字がサブシーケンスの先頭でない場合は、その文字を保持文字列に入れます。これは文字列を構築します。それがサブシーケンスを開始する場合、それらの文字を別の保持ストリングに追加します。サブシーケンスに対して一致する数をマークします。各文字を1つずつ、すでにサブシーケンスと一致している場合は、最初の文字と一致するかどうかを確認し、次に一致する次の位置の文字と一致するかどうかを確認します。それがサブシーケンスと一致する場合、その前のすべて(保持ストリング内)がリストに入れられます。
したがって、基本的には、勝つ可能性のあるシーケンスである可能性があるものを追跡する必要があり、サブシーケンスが別のサブシーケンス内にある可能性があることを追跡する必要があります。
複数の保持文字列が必要な場合がありますが、2つの保持文字列を使用する単純なアプローチを実装し、さまざまな例を調べて、別の保持文字列が必要かどうかがわかるまで各ステップで何が起こっているかを書き留めます。