CodeForces 762C Two strings

今天补一下前天的一道题,我果然是太菜了TAT

题面如下:

C. Two strings

You are given two strings a and b. You have to remove the minimum possible number of consecutive (standing one after another) characters from string b in such a way that it becomes a subsequence of string a. It can happen that you will not need to remove any characters at all, or maybe you will have to remove all of the characters from b and make it empty.

Subsequence of string s is any such string that can be obtained by erasing zero or more characters (not necessarily consecutive) from string s.

Input

The first line contains string a, and the second line — string b. Both of these strings are nonempty and consist of lowercase letters of English alphabet. The length of each string is no bigger than 105 characters.

Output

On the first line output a subsequence of string a, obtained from b by erasing the minimum number of consecutive characters.

If the answer consists of zero characters, output «-» (a minus sign).

Examples
Input
hi
bob
Output
-
Input
abca
accepted
Output
ac
Input
abacaba
abcdcba
Output
abcba
Note

In the first example strings a and b don't share any symbols, so the longest string that you can get is empty.

In the second example ac is a subsequence of a, and at the same time you can obtain it by erasing consecutive symbols cepted from string b.

题意:给你两个字符串A,B,让你从B中删除最短的一段连续字符,使得B成为A的子序列。无法办到就输出'-'。

分析:日常暴力一发。枚举左右两个需要删除的区间,并且对每一次剩下来的字符串作匹配,看是否是A的子序列。枚举区间需要O(n^2),匹配需要O(n),复杂度是不能通过的。

这时候我猛然就想起了敬爱的雨神的谆谆教诲:“求最x值最x,不是贪心就是二分。”emmm

这道题的话贪心肯定不靠谱,于是就只能二分了,二分需要删除的区间长度。为了实现这个二分的操作,我们需要先对这两个字符串进行预处理。我们开两个数组pos1,pos2,pos1[i],pos2[i]分别代表字符串B从前往后第i个字符在A串里第一次出现的位置和从后往前倒数第i个字符在A串里第一次出现的位置。于是匹配的时候我们就先judge一手,如果发现对于某个答案mid而言,把left赋为0,right赋为mid+1,若pos1[left]

据说还有一种做法是用双指针扫描,在B字符串中枚举left,向右找到right使得pos1[left]


代码贴下来:

#include
#include
#include
#include
using namespace std;

const int maxn=1e6+7;
int ans,ansl,ansr,alen,blen;
int pos1[maxn],pos2[maxn];
char a[maxn],b[maxn];

void prework(){//预处理两个pos数组的过程
    memset(pos1,0,sizeof(pos1));
    memset(pos2,0,sizeof(pos2));
    alen=strlen(a+1),blen=strlen(b+1);
    int l=1;
    for(int i=1;i<=blen;i++){
        while(l<=alen&&a[l]!=b[i]) l++;
        pos1[i]=l;
        if(l<=alen)
            l++;
    }
    pos1[0]=0;
    pos2[blen+1]=alen+1;
    int r=alen+1;
    for(int i=blen;i>=1;i--){
        while(l>=1&&a[l]!=b[i]) l--;
        pos2[i]=l;
        if(l>=1)
            l--;
    }
}

bool jug(int mid){//判断当前答案mid是否合法
    int l=0,r=mid+1;
    while(r<=blen+1){
        if(pos1[l]>1;
        if(jug(mid))
            r=mid;
        else
            l=mid;
    }
    if(jug(l)) ans=l;//判断l和r哪一个是答案
    else if(jug(r)) ans=r;
    else ans=r+1;
    l=0,r=ans+1;
    ansl=0;
    ansr=blen+1;
    while(r<=blen+1){//分别找到删除区间的左右边界在哪
        if(pos1[l]=1;i--)
//            cout<

你可能感兴趣的:(题解)