リンク:https
://ac.nowcoder.com/acm/contest/7502/I出典:Niuke
制限時間:C / C ++ 1秒、他の言語2秒
スペース制限:C / C ++ 262144K、他の言語524288K
64ビットIO形式:%lld
タイトル説明
ボボには2つの文字列sとtがあります。彼は、次のように、sからxとtからyの2つのサブシーケンスを選択したいと考えています。
+ xは辞書式順序でy以下です。
+ | x |の合計 および| y | は最大です。ここで| s | 文字列sの長さを示します。
次の点に注意してください。
+ xとyの両方が空の文字列である可能性があります。
+サブシーケンスは、残りの要素の順序を変更せずに0個以上の要素を削除することにより、指定されたシーケンスから派生できるシーケンスです。
+文字列xは、xがyの接頭辞(およびx≠yx \neyx= y)であるか、そのようなi(1≤i≤min(∣x∣、∣)が存在する場合、辞書式順序で文字列yよりも小さくなります。 y∣)1 \ le i \ le \ min(| x |、| y |)1≤i≤min(∣x∣、∣y∣))、そのxi <yix_i <y_ixi <yi、および任意の場合j(1≤j<i1 \ le j <i1≤j<i)xj = yjx_j = y_jxj = yj。
説明を入力してください:
入力は、ファイルの終わりで終了するいくつかのテストケースで構成されます。テストケースごとに: 最初の行には文字列sが含まれています。2行目には文字列tが含まれています。 * 1≤∣s∣≤20001 \ le | s | \ le20001≤∣s∣≤2000 * 1≤∣t∣≤20001 \ le | t | \ le20001≤∣t∣≤2000 * | s |の合計 20000を超えない。 * | t |の合計 20000を超えない。 *両方の文字列は英語の小文字のみで構成されます。
出力の説明:
テストケースごとに、| x |の合計を出力します。および| y |。
例1
入る
aaaa bbbb dac abca dac dac
出力
8 7 8
タイトルの意味:a <b(辞書式順序)となるように、2つの文字列s、tからそれぞれサブシーケンスa、bを選択し、aとbの長さの合計の最大値を見つけます。
アイデア: 長さはls、tの長さはltです。これ は 、sの接尾辞 とt の接尾辞の最大値を意味し 、iとjを後ろから前にトラバースします。
(1)、つまり、次の文字はオプションです。
(2)の両方が選択されている場合、このビットは、すべてまたはいずれかを選択することができ 、それは 、または いずれかが選択されている場合 、最大値
(3)このビットはまったく選択できません。1つまたはなしを選択する か、1つを選択するか 、なしを選択して、最大値を取得することができます。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 2010;
int dp[maxn][maxn];
int main()
{
string ss, tt;
while(cin >> ss >> tt)
{
int ls = ss.size(), lt = tt.size();
memset(dp, 0, sizeof(dp));
for(int i = 0; i <= lt; ++i) dp[ls][i] = lt - i;
for(int i = ls - 1; i >= 0; i--) {
for(int j = lt - 1; j >= 0; j--) {
if(ss[i] < tt[j])
dp[i][j] = max(dp[i][j], ls-i + lt-j);
else if(ss[i] == tt[j])
dp[i][j] = max({dp[i][j], dp[i + 1][j + 1] + 2, dp[i + 1][j], dp[i][j + 1]});
else
dp[i][j] = max({dp[i][j], dp[i + 1][j + 1], dp[i + 1][j], dp[i][j + 1]});
}
}
cout << dp[0][0] << endl;
}
}