题面如下:
题意简说:
给你两个字符串:
s
a
n
d
t
s \ and\ t
s and t
t
是
s
的子序列
t是s的子序列
t是s的子序列
找 最小长度字符串
s
t
r
str
str
使
s
t
r
str
str 满足 是
s
s
s的子串 && 使
t
t
t 是
s
t
r
str
str 的子序列
思路 or 题解
因为
t
t
t串长度最多100, 所以我们可以通过
t
t
t串的位置进行求解
我们可以预处理
s
s
s串, 在
i
i
i 位置向右最近的 字符
c
h
ch
ch 的位置
约定:
s
s
s串长度为
n
n
n,
t
t
t串长度为
m
m
m
预处理的时间复杂度为
O
(
n
∗
36
)
O(n * 36)
O(n∗36)
这样我们就可以在
O
(
n
∗
m
)
O(n * m)
O(n∗m)的时间复杂度 去计算出每一个合法区间的长度
合法区域长度最小的区间就是我们求的最优解!
AC代码如下:
const int N = 100009;
string a, b;
int lena, lenb;
int ne[N][45];
int cal(char ch)
{
if (ch >= '0' && ch <= '9')
return ch - '0' + 1;
else
return ch - 'a' + 11;
}
void init()
{
for (int i = 0; i <= lena; i++)
for (int j = 1; j < 40; j++)
ne[i][j] = 0;
}
void solve()
{
cin >> a >> b;
lena = a.size(), lenb = b.size();
init();
a = '#' + a;
b = '#' + b;
for (int i = lena - 1; i >= 1; i--)
{
for (int j = 1; j < 40; j++)
ne[i][j] = ne[i + 1][j];
ne[i][cal(a[i + 1])] = i + 1;
}
int mn = INT_MAX, idx;
for (int i = 1; i <= lena; i++)
{
if (a[i] != b[1])
continue;
int now = i;
bool f = 1;
for (int j = 2; j <= lenb; j++)
{
if (ne[now][cal(b[j])])
now = ne[now][cal(b[j])];
else
{
f = 0;
break;
}
}
if (f)
{
if (now - i + 1 < mn)
{
mn = now - i + 1;
idx = i;
}
}
}
for (int i = idx; i <= idx + mn - 1; i++)
cout << a[i];
cout << '\n';
}
int main()
{
buff;
int _;
cin >> _;
while (_--)
solve();
}