Two strings CodeForces
来源:互联网 发布:java的布尔类型 编辑:程序博客网 时间:2024/06/02 04:14
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; }
- Two strings CodeForces
- codeforces 223B Two strings
- CodeForces 224D - Two Strings
- codeforces-223B-Two Strings
- CodeForces 762C Two strings
- [codeforces] 762C - Two strings 线段树
- Educational Codeforces Round 17-C Two strings
- 【字符串+乱搞】Codeforces 762C Two strings
- Two Strings
- Codeforces Round #138 (Div. 2)D. Two Strings
- Codeforces Round #138 (Div. 1), problem: (B) Two Strings
- Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings
- CodeForces Round #179 (296B) - Yaroslav and Two Strings
- CodeForces 296B Yaroslav and Two Strings (容斥)
- [Educational Codeforces Round 17 C (762C)] Two strings
- Educational Codeforces Round 17 C. Two strings(二分)
- Codeforces 762C Two Strings 二分判定+预处理
- Codeforces 762C Two strings (前缀与后缀)
- UVA 136
- input点击后placeholder中的提示消息消失
- Eclipse项目转换成studio项目
- (练习)java字符串
- JointJS零基础入门04-链接样式
- Two strings CodeForces
- office excel无法打开超链接解决方法
- TextView和ImageView的倾斜
- Java中的集合框架
- execl单元格不为0的时候设置颜色
- 异常行为分析模型设计
- pgrouting路径分析(任意两点之间的最短路径)
- GBDT&Spark mllib
- Git 提示fatal: remote origin already exists 错误解决办法