您的位置:首页 > 其它

Two strings CodeForces - 762C(二分+预处理)

2017-08-22 17:05 225 查看
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 10^5 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).

Example

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.

大致题意:给你两个串s1,s2,你可以删除s2中连续的一段字符,使得剩下的s2串拼接起来成为s1的子序列串。如果存在,输出拼接后s2最长的那种情况,否则将s2串删光,输出-。

思路:假设我们要删除的连续字符的长度为len,len的范围为0到l2(s2串的长度)。可以很容易的看出len具有单调性,所以我们可以二分len,然后枚举所要删除的连续字符的起点,这样的话时间复杂度为nlogn,然后考虑怎么check,如果每次都直接暴力去判断的话那么需要o(n)的时间复杂度,这样总的时间复杂度就达到了n^2logn,T掉了。考虑到每次删完剩下的两段可以看作是s2串的前缀和后缀,所以我们可以先预处理出s2的所有前缀在s1串中最靠前的子序列的末尾位置a,和s2的所有后缀在s1串中最靠后的子序列的开头位置b,存到两个数组中,每次只需比较前者和后者的位置a,b是否满足a < b即可。这样check的时间复杂度就降到了O(1),总的时间复杂度为nlogn。

代码如下

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <bitset>
using namespace std;
const int maxn=1e5+5;
#define ll long long int

char s1[maxn],s2[maxn];
int bef[maxn],nex[maxn];//前缀,后缀。
int l1,l2;
int ans1,ans2;//分别记录删除的起点和长度
int check(int len)
{
for(int i=0;i<=l2-len;i++)
{
if(i==0)//特判一下如果从第一个就开始删
{
if(nex[len]>=0)//此时只要后缀满足是s1的子序列就可以了
{
ans1=0;
ans2=len;
return 1;
}
}
else
{
if(bef[i-1]<nex[i+len])//否则需要满足前缀位置小于后缀位置
{
ans1=i;
ans2=len;
return 1;
}
}
}
return 0;
}
int main()
{
gets(s1);
gets(s2);
l1=strlen(s1);
l2=strlen(s2);
int j=0;
for(int i=0;i<l2;i++)//前缀
{
while(1){
if(j==l1)//如果此时的前缀不是s1的子序列,则赋值为l1,判断的时候必将会大于后缀位置
{
bef[i]=j;
break;
}
if(s2[i]==s1[j])
{
bef[i]=j;
j++;
break;
}
j++;
}
}
j=l1-1;
for(int i=l2-1;i>=0;i--)//后缀
{
while(1){
if(j==-1)//如果此时的后缀不是s1的子序列,则赋值为-1,判断的时候必将会小于前缀位置
{
nex[i]=j;
break;
}
if(s2[i]==s1[j])
{
nex[i]=j;
j--;
break;
}
j--;
}
}
nex[l2]=l1;//可能会把后缀删光

int l=0,r=l2-1;
ans1=-1;
while(r>=l)
{
int mid=(r+l)/2;
if(check(mid))
{
r=mid-1;
}
else
l=mid+1;
}
if(ans1==-1)
printf("-\n");
else
{
for(int i=0;i<ans1;i++)
printf("%c",s2[i]);
for(int i=ans1+ans2;i<l2;i++)
printf("%c",s2[i]);

}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐