题目:


- 题意:给出两段字符串分别为s、t,将t与s的子串进行匹配,求出所有匹配成功的s子串中所有si+1与si的距离最大值.
- 思路:贪心 + 双指针
- 解析:这种贪心匹配之前还未接触过,所以做个笔记,此题贪心策略是从左往右进行扫描,找出t中每一个字符第一次在s中出现的位置,并记录到l数组中,接着从右往左进行扫描,找出t中每一个字符最后一次在s中出现的位置(扫描过程利用two pointers),最后找出r[i] - l[i-1]的最大值即可.
- 详细分析:
- 为什么r[i] - l[i-1]中一定存在答案?
原因为:当我们每一次尽可能的让第i个字符往后靠,第i-1个字符往前靠,那么它们中相差的距离肯定是尽可能大的
- 为什么r[i] - l[i-1]一定能满足所有的t能在s中匹配成功,因为无论是找t中每一个字符第一次在s中出现的位置,还是找t中每一个字符最后一次在s中出现的位置,在找第i个字符时肯定第(i-1)个字符已经找过,那说明第(i-1)个字符的位置肯定在第i个字符前面,所以满足匹配规则
- 代码:
#include<iostream>
#include<string>
using namespace std;
const int N = 2e5 + 5;
string s, t;
int l[N], r[N];
int n, m;
int main()
{
cin >> n >> m;
cin >> s >> t;
int ps = 0, pt = 0;
while(ps < n && pt < m)
{
if(s[ps] == t[pt])
{
l[pt] = ps; //记录t中每一个字符在s中最先出现的位置
pt ++;
}
ps ++;
}
ps = n-1, pt = m-1;
while(ps > 0 && pt > 0)
{
if(s[ps] == t[pt])
{
r[pt] = ps; //记录t中每一个字符在s中最先出现的位置
pt --;
}
ps --;
}
int res = 0;
for(int i = 1; i < m; i++)
res = max(res, r[i] - l[i-1]);
cout << res << endl;
return 0;
}