[CF762C] Two strings - 双指针
Description
给定 (2) 仅包含小写字母字符串 (s) 和 (t),从 (s) 中删除连续的一段字符,使得 (s) 是 (t) 的子序列。最小化删除的数量,并输出执行删除操作后的字符串 (s)。
Solution
预处理 (s) 的每个前缀在 (t) 中从头开始做子序列匹配到的位置,(s) 的每个后缀在 (t) 中从尾反向开始做子序列匹配到的位置,然后双指针处理即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5;
char s[N], t[N];
int a[N], b[N], n, m;
signed main()
{
ios::sync_with_stdio(false);
cin >> t + 1 >> s + 1;
n = strlen(s + 1);
m = strlen(t + 1);
for (int i = 1; i <= n; i++)
{
int j;
for (j = a[i - 1] + 1; j <= m; j++)
if (s[i] == t[j])
break;
if (j <= m)
a[i] = j;
else
a[i] = m + 1;
}
b[n + 1] = m + 1;
for (int i = n; i >= 1; i--)
{
int j;
for (j = b[i + 1] - 1; j >= 1; j--)
if (s[i] == t[j])
break;
if (j >= 1)
b[i] = j;
else
b[i] = 0;
}
int ans = 0, ansx, ansy;
for (int i = 1, j = 2; i <= n; i++)
{
if (i >= j)
j = i + 1;
while (a[i] >= b[j])
j++;
if (i + n - j + 1 > ans)
{
ans = i + n - j + 1;
ansx = i;
ansy = j;
}
}
for (int i = 1; i <= n; i++)
{
if (a[i] <= m && i > ans)
{
ans = i;
ansx = i;
ansy = n + 1;
}
}
for (int i = 1; i <= n; i++)
{
if (b[i] >= 1 && n - i + 1 > ans)
{
ans = n - i + 1;
ansx = 0;
ansy = i;
}
}
// for (int i = 1; i <= n; i++)
// cout << a[i] << " ";
// cout << endl;
// for (int i = 1; i <= n; i++)
// cout << b[i] << " ";
// cout << endl;
if (ans == 0)
{
cout << "-" << endl;
}
else
{
for (int i = 1; i <= ansx; i++)
cout << s[i];
for (int j = ansy; j <= n; j++)
cout << s[j];
cout << endl;
}
}