[CF762C] Two Strings(预处理,二分答案)

题目链接:http://codeforces.com/contest/762/problem/C

题意:两个字符串a、b。希望在a中删掉连续的字符串,使得b是a的子序列。

希望删掉的是连续的字符串,那么可以预处理两个数组pre和suf。

pre(i)表示b[0,i]为a的子序列,a的最短长度。

suf(i)表示b[i,na)为a的子序列,a倒着数的最短长度。

会发现这两个数列是单调的,二分答案len,表示中间删掉的字符串长度为len。O(n)枚举a删除的起始点,判断即可。

注意判断时枚举到起点为0,即无前缀的时候,要判断这时后缀长度是否满足条件。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 100100;
 5 char a[maxn], b[maxn];
 6 int na, nb;
 7 int pre[maxn], suf[maxn];
 8 bool exflag;
 9 string ret;
10 
11 bool ok(int len) {
12     for(int i = 0; i <= nb-len; i++) {
13         if((i == 0 && suf[len] >= 0) || pre[i-1] < suf[i+len]) {
14             ret = "";
15             exflag = 1;
16             for(int j = 0; j < i; j++) ret += b[j];
17             for(int j = i+len; b[j]; j++) ret += b[j];
18             return 1;
19         }
20     }
21     return 0;
22 }
23 
24 int main() {
25     // freopen("in", "r", stdin);
26     memset(a, 0, sizeof(a));
27     memset(a, 0, sizeof(b));
28     while(~scanf("%s%s",a,b)) {
29         na = strlen(a); nb = strlen(b);
30         memset(pre, 0, sizeof(pre));
31         memset(suf, 0, sizeof(suf));
32         int p = 0;
33         for(int i = 0; i < nb; i++, p++) {
34             while(p < na && a[p] != b[i]) p++;
35             pre[i] = p;
36         }
37         p = na - 1;
38         for(int i = nb-1; i >= 0; i--, p--) {
39             while(p >= 0 && a[p] != b[i]) p--;
40             suf[i] = p;
41         }
42         suf[nb] = na;
43         // for(int i = 1; i <= nb; i++) printf("%d ", pre[i]); printf("
");
44         // for(int i = 1; i <= nb; i++) printf("%d ", suf[i]); printf("
");
45         exflag = 0; ret = "";
46         int lo = 0, hi = nb - 1;
47         while(lo <= hi) {
48             int mid = (lo + hi) >> 1;
49             if(ok(mid)) hi = mid - 1;
50             else lo = mid + 1;
51         }
52         if(!exflag) puts("-");
53         else cout << ret << endl;
54         memset(a, 0, sizeof(a));
55         memset(a, 0, sizeof(b));
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/kirai/p/6874482.html