您的位置:首页 > 其它

Codeforces 868 D Huge String

2017-10-21 14:41 495 查看
题目地址

题意:给你n个字符串(0和1),然后给你m次操作,每一次操作都是把两个字符串拼接起来得到的一个新的字符串放入数组n+i的位置上,然后判断出这个新的字符串包含的最长0和1的全排列(全部)。

思路:看了别人的说法才知道可以直接暴力枚举,每次把字符串拼接起来,放入最后一个位置,再对这个字符串直接通过位运算来生成长度为K的全排列,看这个子字符串是不是拼接字符串的子串。然后把最大的k与拼接的两个字符串的最大K进行比较,取最大的放入数组,准备下一次查询。

其实最重要的是为什么可以用暴力枚举,因为每个字符串的长度最多为100,在最理想的条件下只能有6的全部全排列字符串,然而我们进行拼接是不会增加K的,所以我们就可以使用暴力的方法。但是为了防止

MLE我们对于拼接以后字符串大于1000的就取他的前缀和后缀各500个字符就好了。

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#define N 1010
#define M 2000010//双倍
#define LL __int64
#define inf 0x3f3f3f3f
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
#define getMid (l+r)>>1
#define movel ans<<1
#define mover ans<<1|1
using namespace std;
const LL mod = 1000000007;
const double eps = 0.001;
string str
;
int num
;
int solve(int x) {
for (int i = 1; i <= 10; i++) {
for (int j = 0; j < (i << i); j++){//遍历每一个串
string newstr = "";
for (int k = 0; k <= i - 1; k++) {//把数字转为字符串
if (j&(1 << k)) {
newstr += '1';
}
else {
newstr += '0';
}
}
if (str[x].find(newstr)==str[x].npos) return i - 1;
}
}
}
int main() {
cin.sync_with_stdio(false);
int n, m;
int a, b;
while (cin >> n) {
memset(num, -1, sizeof(num));
for (int i = 1; i <= n; i++) {
cin >> str[i];
}
cin >> m;
for (int i = 1; i <= m; i++) {
cin >> a >> b;
if (num[a] == -1) {
solve(a);
}
if (num[b] == -1) {
solve(b);
}
str[n + i] = str[a] + str[b];
if(str[n+i].length()>1000) str[n + i] = str[n + i].substr(0, 500) + str[n + i].substr(str[n + i].length() - 500, 500);
num[n + i] = max(max(num[a], num[b]), solve(n + i));
cout << num[n + i] << endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: