文字列なしの最長サブシーケンス


8

サブストリングとしてYを含まないストリングXで最長のサブシーケンスを見つける動的プログラミングアルゴリズムはありますか?この問題は、最長の共通サブシーケンスや文字列など、他のDP文字列アルゴリズムと非常に似ているように見えます。オーバーラップするYの発生を処理できる必要があります。

これは2状態のDP問題である可能性があります。状態[s_pos、t_pos]は、ストリングT [t_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;
}

1
X内のすべての部分文字列Yを見つけ、それらの間の最も長いギャップを見つけます
ラチェットフリーク

それらが重なるとどうなりますか?(発生)
user83834 2013年

1
完全な解決策を提供するには、私の趣味には宿題が多すぎます。ヒントは次のとおりです。特定の位置について、その位置までの最長のサブシーケンスとその位置で終了する最長のサブシーケンスがわかっている場合、次の位置についてそれを更新できますか?
AProgrammer 2013年

@AProgrammer次は、ポジションi + 1ですか?
user83834 2013年

@ratchetfreak XがOPPOPPOでYがOPPOの場合、ギャップはありません。しかし、最も長いサブシーケンスは、中央のO:OPPPPOを無視することです。
user83834 2013年

回答:


1

これでうまくいくはずです。私はそれをベーシックに似たメタコードで書いた。

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

0

主な問題は、elseステートメント内のforループであり、関数を再帰的に呼び出すことです。

再帰または反復のいずれかのアプローチを選択しますが、それらを混合することは間違っているようです。

私は反復的なアプローチで行きます。

関数の外に空のリストを作成します。

次にを呼び出しますsolve

この関数でこのアプローチを試してください:

文字列をループします。現在の文字がサブシーケンスの先頭でない場合は、その文字を保持文字列に入れます。これは文字列を構築します。それがサブシーケンスを開始する場合、それらの文字を別の保持ストリングに追加します。サブシーケンスに対して一致する数をマークします。各文字が1つずつ、すでにサブシーケンスと一致している場合は、最初の文字と一致するかどうか、次に一致する次の位置の文字と一致するかどうかを確認します。それがサブシーケンスと一致する場合、その前のすべて(保持ストリング内)がリストに入れられます。

したがって、基本的には、勝つ可能性のあるシーケンスである可能性があるものを追跡する必要があり、サブシーケンスが別のサブシーケンス内にある可能性があることを追跡する必要があります。

複数の保持文字列が必要な場合がありますが、2つの保持文字列を使用する単純なアプローチを実装し、さまざまな例を調べて、別の保持文字列が必要かどうかがわかるまで各ステップで何が起こっているかを書き留めます。


-1

Y部分文字列を正規表現のように扱い、DFAに変換する必要があると思います。次に、DFAを介して入力を渡し、一致してからの経過時間を追跡します。入力のサイズが一致する文字列の複雑さよりもはるかに大きいと仮定すると、線形時間の問題のようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.