CF1492 C.Maximum width(贪心、双指针)

题目:

  • 题意:给出两段字符串分别为s、t,将t与s的子串进行匹配,求出所有匹配成功的s子串中所有si+1与si的距离最大值.
  • 思路:贪心 + 双指针
  • 解析:这种贪心匹配之前还未接触过,所以做个笔记,此题贪心策略是从左往右进行扫描,找出t中每一个字符第一次在s中出现的位置,并记录到l数组中,接着从右往左进行扫描,找出t中每一个字符最后一次在s中出现的位置(扫描过程利用two pointers),最后找出r[i] - l[i-1]的最大值即可.
  • 详细分析:
    1. 为什么r[i] - l[i-1]中一定存在答案?
      原因为:当我们每一次尽可能的让第i个字符往后靠,第i-1个字符往前靠,那么它们中相差的距离肯定是尽可能大的
    2. 为什么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;
}

posted @ 2021-03-14 22:15  ~K2MnO4  阅读(202)  评论(0)    收藏  举报