本文已参与「新人创作礼」活动,一起开启掘金创作之路。
@TOC
Codeforces Round #704 (Div. 2)-C. Maximum width
传送门 Time Limit: 2 seconds Memory Limit: 512 megabytes
Problem Description
Your classmate, whom you do not like because he is boring, but whom you respect for his intellect, has two strings: of length and of length .
A sequence , where , is called beautiful, if for all from to . The width of a sequence is defined as .
Please help your classmate to identify the beautiful sequence with the maximum width. Your classmate promised you that for the given strings and there is at least one beautiful sequence.
Input
The first input line contains two integers and () — the lengths of the strings and .
The following line contains a single string of length , consisting of lowercase letters of the Latin alphabet.
The last line contains a single string of length , consisting of lowercase letters of the Latin alphabet.
It is guaranteed that there is at least one beautiful sequence for the given strings.
Output
Output one integer — the maximum width of a beautiful sequence.
Sample Input
5 3
abbbc
abc
Sample Onput
3
Note
In the first example there are two beautiful sequences of width : they are and .
In the second example the beautiful sequence with the maximum width is .
In the third example there is exactly one beautiful sequence — it is .
In the fourth example there is exactly one beautiful sequence — it is .
题目大意
两个字符串s和t长度分别是n和m。 在s从左到右选一些字母组成t。 问s中所有选中的字符中,最大间距是多少。
题目保证能从s中选出t。
题目分析
要使间距最大,就要t中的某两个相邻的字母在s中选择时,第一个字母尽可能往前,第二个字母尽可能往后,这样才能使间距最大。
如s(abbbc
)中选择t(abc
),看t中相邻两个字母,先看a
和b
,a
要选的尽可能靠前(其实就一种选择),所以选第1
个。b
要选的尽可能靠后(可以选第2~4个),所以选第4
个。这样的话它的最大间距就是4-3=3
。同理看b
和c
时,应分别选择第2
个和第5
个,间距同样是5-2=3
。所以最大间距是3
。
解题思路
先从前往后遍历一遍,得到t中每个字母最靠前能选到s的第几个; 再从后往前遍历一遍,得到t中每个字母最靠后能选到s的第几个。 考虑所有t中相邻的两个字母,看看第一个字母最靠前,第二个字母最靠后,间距是多少。 更新最大间距,直到遍历完t。
AC代码
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
char s[200010];
char t[200010];
int zuiQian[200010]; //最靠前能选到s中的第几个
int zuiHou[200010]; //最靠后能选到s中的第几个
int main()
{
int n, m, M = 1;
scanf("%d%d", &n, &m);
scanf("%s", s);
scanf("%s", t);
int lastT = -1;
for (int i = 0; i < m; i++)
{
while (s[++lastT] != t[i]) //找到s中第一个没有选过的并且与t的下一个相同的字母。
;
zuiQian[i] = lastT;
}
lastT = n;
for (int i = m - 1; i >= 0; i--)
{
while (s[--lastT] != t[i])
;
zuiHou[i] = lastT;
}
for (int i = 1; i < m; i++)
{
M = max(M, zuiHou[i] - zuiQian[i - 1]); //更新最大值
}
printf("%d\n", M);
return 0;
}
注意事项
while (s[++lastT] != t[i]);
是打比赛时确定s中下一个位置的简便写法。
学会的话打比赛会快亿点点,但是小心不要用错了哦。
同步发文于我的CSDN