Educational Codeforces Round 17 C. Two strings(字符串前缀后缀处理,好题)

来源:互联网 发布:ubuntu arp攻击 编辑:程序博客网 时间:2024/05/21 06:32

C. Two strings
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 105 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).

Examples
input
hibob
output
-
input
abcaaccepted
output
ac
input
abacabaabcdcba
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 长度1e5 ,问题 串2 去掉一个最短连续子串,使得剩下的串拼起来是 串1 的一个子串。求这个子串,若为空输出“-”。


题解:

枚举B的子串其实只要枚举删除的位置就好了,因为B删除的部分是连续的字符串而且只能删一次。可以把字符串B看成三部分。

                    | 左边部分 || 删除部分 || 右边部分 |

左边部分、右边部分可能为空。 
其实就是前后缀,先求出B各个前缀需要A前缀的长度,再求出B各个后缀需要A后缀的长度,

比如说字符串A是 abacaba,字符串B是 abcdcba ,B的前缀依次是a、ab、abc、abcd….,后缀依次是a、ba、cba、dcba、cdcba….,前缀a需要字符串A的前缀长度为1(a),前缀ab需要字符串A的前缀长度为2(ab),前缀abc需要字符串A的前缀长度为4(abac)….

或者说

记录串a每个字符,是串b最长的属于串a这个字符之前的子序列坐标的最后一个,比如  串a : ababa 串 b: abc, 那么pre[1] = 1,pre[2] = 2, pre[3] = 2, pre[4] = 2 ,pre[3]= 2指的是 串b 中 ab 是串a前三个的字符的子序列,同理记录串a的后缀,这样的目的是,很方便的知道每个字符 往前对应几个b 往后对应几个b,要删除的那一串字符就是 suf - pre,不用暴力枚举了,这里因为这三个串都是连续的所以可以这样前缀后缀,在suf-pre的时候,有的题解是二分来找,其实不用,因为是前缀,pre[i+1] 肯定 >= pre[i],suf[i-1] >= suf[i],而且又要求是最短的所以suf[i] - pre[i-1]肯定是最短的,枚举i的时候,pre[i-1]肯定是前i个最大的。。所以直接-pre[i-1]就行。。


#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<queue>#include<stack>using namespace std;#define rep(i,a,n) for (int i=a;i<n;i++)#define per(i,a,n) for (int i=n-1;i>=a;i--)#define pb push_back#define fi first#define se secondtypedef vector<int> VI;typedef long long ll;typedef pair<int,int> PII;const int inf=0x3fffffff;const ll mod=1000000007;const int maxn=1e5+100;char a[maxn],b[maxn];int pre[maxn],suf[maxn];int main(){    scanf("%s%s",a+1,b+1);    int l1=strlen(a+1),l2=strlen(b+1);    int j=1;    rep(i,1,l1+1)    {        if(a[i]==b[j])        {            pre[i]=pre[i-1]+1;j++;        }        else pre[i]=pre[i-1];    }    j=l2;    rep(i,1,l1+2) suf[i]=l2+1;    per(i,1,l1+1)    {        if(a[i]==b[j])        {            suf[i]=suf[i+1]-1;j--;        }        else suf[i]=suf[i+1];    }    int ans=inf,p1=-1,p2=-1;        rep(i,1,l1+2)     //注意从i=1开始,从l1+1结束    {        if(suf[i]-pre[i-1]-1>0&&suf[i]-pre[i-1]<ans)        {            ans=suf[i]-pre[i-1];            p1=pre[i-1]+1,p2=suf[i]-1;        }    }    if(p1==1&&p2==l2)    {        puts("-");        return 0;    }    rep(i,p1,p2+1) b[i]='*';    rep(i,1,l2+1) if(b[i]!='*') printf("%c",b[i]);    puts("");    return 0;}


0 0
原创粉丝点击