Codeforces - 1203D2 (思维)
题目链接:http://codeforces.com/problemset/problem/1203/D2
题目大意:给出一段长串s1和它的一段非连续子串s2,求s1最长的连续删除区间,使得s2仍为s1的非连续子串
分析:最大分割情况只可能是两种,一种是最左端或者最右端删去一大段,另一种是中间任意两个字母间删去一大段
先看第一种,那么肯定是要找到s2在s1中的最左相同点和最右相同点,很简单
另一种,删去的区间端点两个字母肯定是s2中相邻的字母,即保证删去中间一段没用的,仍是子串 例如s1:abbccbbbcccddde s2: ab
那么最长区间肯定是找到s1最左端满足条件的a,再找到s1最右端满足条件的b,中间都是可以删的,如果s2:abd 就找到s1最左端满足条件的b,再找到s1最右端满足条件的d,作差值,然后取max
挺有趣的一道题。列为有趣的cf题,当时是真写不出来,看题解居然这么简单,一直想到序列自动机去了,还真是想多了
代码:
#include <bits/stdc++.h>
using namespace std;
char a[200005];
char b[200005];
int from[200005];
int to[200005];
int main()
{
cin >> a >> b;
int len = strlen(a);
int len2 = strlen(b);
int i,j;
j = 0;
for ( i=0; i<len; i++ ) { // 从前往后找
if ( j==len2 ) {
break ;
}
if ( a[i]==b[j] ) {
from[j] = i;
j ++;
}
}
j = len2-1;
for ( i=len-1; i>=0; i-- ) { // 从后往前找
if ( j==-1 ) {
break ;
}
if ( a[i]==b[j] ) {
to[j] = i;
j --;
}
}
int ans = 0;
ans = max( max(from[0],to[0]),ans ); // 取左边界无用部分
ans = max( len-1-min(from[len2-1],to[len2-1]),ans ); // 取右边界无用部分
for ( i=1; i<len; i++ ) {
ans = max(ans,to[i]-from[i-1]-1); // 好好理解这个部分
}
cout << ans << endl;
return 0;
}