http://codeforces.com/contest/762/problem/C

第一个串str[],第二个sub[]

预处理出prefix[i]表示sub的前i位和str[]的最长lcs去到str[]的最小的位置,如果某一位i不成立了,就设为inf

由于处理的时候,指针指向str[]的是单调递增的,所以预处理复杂度O(n),同样预处理suffix数组。

那么就是求一个位置,使得两个数组不会相交。

但是如果会相交,那么应该让那个数组退后一步呢,一开始用数组相邻差的绝对值来确定,因为移动得多的那个必定更优。

但是不然,test5就知道了。

于是乎就直接处理出所有的prefix[i],所对应的最优suffix[],这个可以在suffix[]中二分搞定。

话说二分可真有用。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
vector<int>pos[];
const int maxn = 1e5 + ;
char str[maxn], sub[maxn];
int lenstr, lensub;
int L, R;
int prefix[maxn];
int suffix[maxn];
void init() {
int p1 = ;
for (int i = ; i <= lensub; ++i) {
if (pos[sub[i] - 'a'].size() == ) break;
if (pos[sub[i] - 'a'].back() <= p1) break;
prefix[i] = upper_bound(pos[sub[i] - 'a'].begin(), pos[sub[i] - 'a'].end(), p1) - pos[sub[i] - 'a'].begin();
prefix[i] = pos[sub[i] - 'a'][prefix[i]];
p1 = prefix[i];
}
// for (int i = 1; i <= lensub; ++i) {
// cout << prefix[i] << " ";
// }
p1 = lenstr;
for (int i = lensub; i >= ; --i) {
while (p1 >= ) {
if (str[p1] == sub[i]) break;
p1--;
}
if (p1 == ) break;
suffix[i] = p1;
p1--;
}
// for (int i = 1; i <= lensub; ++i) {
// cout << suffix[i] << " ";
// }
}
void work() {
scanf("%s%s", str + , sub + );
lenstr = strlen(str + );
lensub = strlen(sub + );
memset(prefix, 0x3f, sizeof prefix);
memset(suffix, -, sizeof suffix);
for (int i = ; i <= lenstr; ++i) {
pos[str[i] - 'a'].push_back(i);
}
prefix[] = -;
suffix[lensub + ] = inf;
init();
int pos1 = inf, pos2 = inf;
for (int i = ; i <= lensub; ++i) {
if (prefix[i] == inf) {
pos1 = i - ;
break;
}
}
for (int i = lensub; i >= ; --i) {
if (suffix[i] == -) {
pos2 = i + ;
break;
}
}
if (prefix[] == inf && suffix[lensub] == -) {
cout << "-" << endl;
return;
}
if (pos1 == inf || pos2 == inf) {
cout << sub + << endl;
return;
}
if (pos1 == ) {
assert(pos2 != lensub + );
for (int i = pos2; i <= lensub; ++i) {
printf("%c", sub[i]);
}
return;
}
if (pos2 == lensub + ) {
for (int i = ; i <= pos1; ++i) {
printf("%c", sub[i]);
}
return;
}
int anslen = -;
for (int i = ; i <= pos1; ++i) {
int topos = upper_bound(suffix + pos2, suffix + + lensub, prefix[i]) - suffix;
// cout << suffix[topos] << endl;
if (anslen < i + lensub - topos + ) {
anslen = i + lensub - topos + ;
L = i + ;
R = topos - ;
}
}
// cout << L << " " << R << endl;
for (int i = ; i <= lensub; ++i) {
if (i == L) {
i = R;
continue;
}
printf("%c", sub[i]);
} } int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}

C. Two strings 二分 + 预处理的更多相关文章

  1. NOIP2015聪明的质检员[二分 | 预处理]

    背景 NOIP2011 day2 第二题 描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi .检验矿 ...

  2. Codeforces Round #321 (Div. 2) B 二分+预处理

    B. Kefa and Company time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  3. HDU 6274 二分+预处理(CCPC K题

    #include"bits/stdc++.h" #define db double #define ll long long #define vec vector<ll> ...

  4. [luoguP3092] [USACO13NOV]没有找零No Change(状压DP + 二分)

    传送门 先通过二分预处理出来,每个硬币在每个商品处最多能往后买多少个商品 直接状压DP即可 f[i]就为,所有比状态i少一个硬币j的状态所能达到的最远距离,在加上硬币j在当前位置所能达到的距离,所有的 ...

  5. EC R 86 D Multiple Testcases 构造 贪心 二分

    LINK:Multiple Testcases 得到很多种做法.其中O(n)的做法值得一提. 容易想到二分答案 check的时候发现不太清楚分配的策略. 需要先考虑如何分配 容易发现大的东西会对小的产 ...

  6. 「Poetize3」Heaven Cow与God Bull

    描述 Description 给定一个整数n,求一个整数m,满足m<=n,并且m/phi(m)的值最大.注:phi(m)代表m的欧拉函数,即不大于m且与m互质的数的个数. 题解:m/phi(m) ...

  7. D. 实验室传染病

    D. 实验室传染病 题意 给出 n 个人的位置,以及每个人的传染范围,当一个人患病时,他的传染范围内(包括边界上)的人全部会被感染并继续向外传播. 求以每个人为传染源最多有多少人被感染. 分析 首先二 ...

  8. 【倍增】Tak and Hotels II @ABC044&ARC060/upcexam6463

    6463: Tak and Hotels II 时间限制: 1 Sec  内存限制: 128 MB 题目描述 N hotels are located on a straight line. The ...

  9. CF #442 div2

    A 判断下5个名字出现了几次.pre数据巨弱,就这么一水题在std测刷掉了非常多的人.. /** @Date : 2017-10-24 16:04:41 * @FileName: A.cpp * @P ...

随机推荐

  1. VC++如何折叠代码

    工具-选项,然后在文本编辑器,C/C++中的格式设置,把大纲语句块设置为True   这样之后,还是不能像C#一样使用region折叠代码,但是可以方法和if语句都会自动显示可以折叠.   使用#pr ...

  2. ZOJ 3632 Watermelon Full of Water (线段树 区间更新 + dp)

    题目大意: 让每天都能吃到西瓜. 最少须要花多少钱. 思路分析: dp[pos] 就表示  要让 前i天每天都有西瓜吃.最少须要花多少钱. 那么假设你买这个西瓜的话. 那么这个西瓜能吃的持续时间都要更 ...

  3. API Copy Big FIles

    public class ApiCopyFile { private const int FO_COPY = 0x0002; private const int FOF_ALLOWUNDO = 0x0 ...

  4. APUE 线程 - 程序清单

    APUE 线程 - 程序清单 程序清单11-1 打印线程ID #include "util.h" #include<pthread.h> pthread_t ntid; ...

  5. leetcode:238. Product of Array Except Self(Java)解答

    转载请注明出处:z_zhaojun的博客 原文地址 题目地址 Product of Array Except Self Given an array of n integers where n > ...

  6. 【iOS系列】-A server with the specified hostname could not be found.问题解决

    [iOS系列]-A server with the specified hostname could not be found.问题解决 Reveal 在iOS开发中可以方便查看界面的布局,较为方便的 ...

  7. CUDA编程(十)使用Kahan&#39;s Summation Formula提高精度

    CUDA编程(十) 使用Kahan's Summation Formula提高精度 上一次我们准备去并行一个矩阵乘法.然后我们在GPU上完毕了这个程序,当然是非常单纯的把任务分配给各个线程.也没有经过 ...

  8. JDBC访问数据库查询信息的步骤(硬编码格式)

    1 Class.forName()加载驱动 2 DriverManager获取Connect连接 3 创建Statement执行SQL语句 4 返回ResultSet查询结果 5释放资源 packag ...

  9. 通过Mesos、Docker和Go,使用300行代码创建一个分布式系统

    [摘要]虽然 Docker 和 Mesos 已成为不折不扣的 Buzzwords ,但是对于大部分人来说它们仍然是陌生的,下面我们就一起领略 Mesos .Docker 和 Go 配合带来的强大破坏力 ...

  10. 2015年北京网赛 boxes(bfs)

    题目链接: http://hihocoder.com/problemset/problem/1233 题目描述: 给定最多七个箱子,每个箱子的重量都不相同,每次都可以将一个箱子放在相邻的位置上,如果相 ...