题目链接: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;
}