Educational Codeforces Round 17 C 二分

题目链接:http://codeforces.com/contest/762/problem/C

题意:两个字符串 s1 s2 长度1e5 ,问题 串2 去掉一个最短连续子串,使得剩下的串拼起来是 串1 的一个子串。

思路:预处理s2从头匹配最远延伸以及从尾匹配的最远延伸,之后利用这两个数组,可以通过二分答案o(n)判断解决问题

备注:寒假摸鱼。。

代码: 

#include<bits/stdc++.h>
#define bug(x) cout<<"bug "<<x<<endl;
using namespace std;
#define ll long long
const int maxn=1e6+10;
string s1,s2;
int a[maxn],b[maxn];

void init(){
    memset(a,-1,sizeof(a));
    memset(b,-1,sizeof(b));
    int idx=-1;
    for(int i=0;i<s2.size();i++){
        idx++;
        while(s2[i]!=s1[idx]&&idx<s1.size()){
            idx++;
        }
        if(idx>=s1.size()) break;
        a[i]=idx;
    }
    idx=s1.size();
    for(int i=s2.size()-1;i>=0;i--){
        idx--;
        while(s2[i]!=s1[idx]&&idx>=0){
            idx--;
        }
        if(idx<0) break;
        b[i]=idx;
    }
}

int ok(int x){
    if(b[x]!=-1) return 0;
    if(a[s2.size()-x-1]!=-1) return s2.size()-x;
    for(int i=1;i+x<s2.size();i++){
        if(a[i-1]!=-1&&b[i+x]!=-1&&a[i-1]<b[i+x])
            return i;
    }
    return -1;
}

int main(){
    cin>>s1>>s2;
    init();
    int ans=0;
    int lo=0,hi=s2.size();
    while(lo<=hi){
        int mid=(lo+hi)/2;
        if(ok(mid)!=-1) hi=mid-1;
        else lo=mid+1;
    }
    if(lo>=s2.size()) puts("-");
    else{
        int x=ok(lo);
        for(int i=0;i<x;i++) cout<<s2[i];
        for(int i=x+lo;i<s2.size();i++) cout<<s2[i];
        puts("");
    }
    return 0;
}



原文地址:https://www.cnblogs.com/zhangxianlong/p/10672519.html