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。
代码如下
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; }
相关文章推荐
- Professor GukiZ and Two Arrays CodeForces - 620D (二分好题)
- Codeforces edu 6. D Professor GukiZ and Two Arrays 二分搜索 枚举
- 【Educational Codeforces Round 6D】【暴力 SET二分】Professor GukiZ and Two Arrays
- Educational Codeforces Round 6 D. Professor GukiZ and Two Arrays(二分 | two pointers)
- Professor GukiZ and Two Arrays CodeForces - 620D (暴力枚举+二分搜索)
- Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings
- Educational Codeforces Round 6 D. Professor GukiZ and Two Arrays 二分
- Codeforces Round #179 (Div. 2) B (codeforces 296b) Yaroslav and Two Strings
- codeforces C. Remembering Strings 状态压缩-预处理
- Codeforces Round #447 (Div. 2) D. Ralph And His Tour in Binary Country 二叉树、预处理、二分、数据结构
- Educational Codeforces Round 6 D. Professor GukiZ and Two Arrays(二分 | two pointers)
- Educational Codeforces Round 11 C. Hard Process(尺取 二分 区间天数最多
- Codeforces Round #Pi (Div. 2) D. One-Dimensional Battle Ships 二分 stl应用
- D. One-Dimensional Battle Ships-二分答案-Codeforces Round #Pi (Div. 2)
- Codeforces Round #299 (Div. 2) D. Tavas and Malekas KMP+预处理、string suffix structures
- Educational Codeforces Round 2D. Area of Two Circles' Intersection
- Educational Codeforces Round 2 D. Area of Two Circles' Intersection
- Alice, Bob, Two Teams CodeForces - 632B
- Codeforces Round #402 (Div. 2) D(简单)(二分)
- Codeforces Round #384 (Div. 2)E(状压dp+二分,好题)