题目链接:传送门

思路:

由于只能翻转一次子串,就相当于找出两个不连续的子串,把在后面的一个子串翻转过来,和第一个子串拼接。

因为题目仅要求子串中的字符不重复,所以字符的先后顺序无关,翻转的操作就相当于:

选出两个不连续的子串,且他们没有相同的字符,两个子串的长度之和就是答案的一种可能。

题目中反复强调,给出的字符串只有前20个字母[a, t],考虑到$2^{20} = 10^{6}, 2^{26} = 6*10^{7}$,显然在疯狂暗示:要用状压来做这题。

所以考虑二进制状压字符集合。


一个朴素的想法

令集合X = {'a', 'b',..., 't'},用|X|表示集合X的大小。

预处理出集合X的所有有效子集(在原字符串中能找得到)。时间复杂度为O(n*|X|) = 2*$10^{6}$。

然后再枚举X的子集A,和集合A在X中的补集B的子集C,若C是有效的(在原字符串中能找到),则|A|+|C|就是答案的一种可能。

这样做的总时间复杂度是O($2^{|X|}* 2^{|X|}$ + n*|X|) = 1e12,显然会TLE。


题解:

实际上,我们在枚举集合B的子集C的时候,如果我们能知道集合B的有效子集的大小的最大值max{|C|},就可以用|A|+max{|C|}以O(1)的时间来更新答案了。时间复杂度可以下降到O($2^{|X|}$)

接下来考虑如何预处理出max{|C|}。

如果用f[mask]表示,以mask二进制表示的集合S的最大有效子集的大小,那么:

如果S是有效的:f[mask] = |S|

否则:f[mask] = max{f[mask^(1<<i)] | 0 < i < |X| && mask&(1<<i) > 0}

这里的处理是$O(|X|*2^{|X|}) = 2*10^{7}$,是可行的。


代码:$O(|X|*2^{|X|} + |X|*n)$

 #include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x)
#define sz(x) ((int)x.size())
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; /** fast read **/
template <typename T>
inline void read(T &x) {
x = ; T fg = ; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -;
ch = getchar();
}
while (isdigit(ch)) x = x*+ch-'', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
#define MAXMASK 20 int f[mk(MAXMASK)]; // f[mask] = mask's max number of different characters
int main()
{
string s;
cin >> s; int n = s.size();
for (int i = ; i < n; i++) {
int mask = ;
for (int j = ; j < MAXMASK && i+j < n; j++) {
int b = s[i+j] - 'a';
if (mask & mk(b))
break;
mask |= mk(b);
f[mask] = j+;
}
}
for (int mask = ; mask < mk(MAXMASK); mask++) {
for (int i = ; i < MAXMASK; i++) if (mask & mk(i)){
f[mask] = max(f[mask], f[mask ^ mk(i)]);
}
}
int ans = ;
for (int mask = ; mask < mk(MAXMASK); mask++) {
int mask1 = (mk(MAXMASK)-) ^ mask;
ans = max(ans, f[mask] + f[mask1]);
}
cout << ans << endl; return ;
}

Codeforces1234F. Yet Another Substring Reverse(状压dp)的更多相关文章

  1. fzu2188 状压dp

    G - Simple String Problem Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...

  2. HDU 1074 Doing Homework【状压DP】

    Doing Homework Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he ...

  3. 【XSY2745】装饰地板 状压DP 特征多项式

    题目大意 你有\(s_1\)种\(1\times 2\)的地砖,\(s_2\)种\(2\times 1\)的地砖. 记铺满\(m\times n\)的地板的方案数为\(f(m,n)\). 给你\(m, ...

  4. Codeforces Beta Round #8 C. Looking for Order 状压dp

    题目链接: http://codeforces.com/problemset/problem/8/C C. Looking for Order time limit per test:4 second ...

  5. 状压DP的总结

    状压dp的标志 ①数据小 ②通过题目所给出的条件以后得到的特征集合小 一:CF259div2 D: 题目大意:保证b[i]中每个数互质,给出a[i],然后求1~n的abs(a[i]-b[i])最小.a ...

  6. UVa 1204 Fun Game (状压DP)

    题意:有一些小孩(至少两个)围成一圈,有 n 轮游戏,每一轮从某个小孩开始往左或者往右伟手帕,拿到手帕写上自己的性别(B,G),然后以后相同方向给下一个. 然后在某个小孩结束,给出 n 轮手帕上的序列 ...

  7. FZU - 2218 Simple String Problem(状压dp)

    Simple String Problem Recently, you have found your interest in string theory. Here is an interestin ...

  8. 状压DP之LGTB 与序列

    题目 思路 这道题竟然是状压DP,本人以为是数论,看都没看就去打下一题的暴力了,哭 \(A_i\)<=30,所以我们只需要考虑1-58个数,再往后选的话还不如选1更优,注意,1是可以重复选取的, ...

  9. 7月15日考试 题解(链表+状压DP+思维题)

    前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...

  10. Atcoder Regular Contest 093 D - Dark Horse(组合数学+状压 dp)

    Atcoder 题面传送门 & 洛谷题面传送门 常规题,简单写写罢((( 首先 \(1\) 的位置是什么不重要,我们不妨钦定 \(1\) 号选手最初就处在 \(1\) 号位置,最后答案乘个 \ ...

随机推荐

  1. Java中参数的引用传递和值传递

    1.一些定义 值传递:把实际传入参数的值,在内存中赋值一份 引用传递:传入的是实际参数的地址 2.传递基本类型的参数 因为Java是值传递,那就不难理解下面的代码不交换任何值 swap(Type ar ...

  2. Mac OS下Flutter环境搭建记录,VS Code开发

    安装Flutter 获取FlutterSDK 终端cd进入SDK安装目录,比如 cd ~/FlutterSDK 由于在国内访问Flutter有时可能会受到限制,Flutter官方为中国开发者搭建了临时 ...

  3. lr_save_string和sprintf、lr_eval_string的使用

    一.lr_save_string函数 1.该函数主要是将程序中的常量或变量保存为参数: //将常量保存为参数 lr_save_string("777","page&quo ...

  4. 卡死浏览器使IPhone的自带safari打开重启的JS循环代码

    <html> <body> <script> var total=""; for (var i=0; i < 1000000; i++) ...

  5. python正则表达式 分割字符串

    使用或 标准的正则表达式有小括号,但是python的没有 # -*- coding: utf-8 -*- import sys import re import sys reload(sys) sys ...

  6. Web.Config全攻略

    一.认识Web.config文件   Web.config 文件是一个xml文本文件,它用来储存 asp.NET Web 应用程序的配置信息(如最常用的设置asp.NET Web 应用程序的身份验证方 ...

  7. Selenium学习之==>Switch与SelectApi接口详解

    Switch 我们在UI自动化测试时,总会出现新建一个tab页面.弹出一个浏览器级别的弹框或者是出现一个iframe标签,这时我们用WebDriver提供的Api接口就无法处理这些情况了.需要用到Se ...

  8. gzip, deflate delphi xe 2 解码 成功 哈哈

    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 http://bbs.csdn.net/topics/190020986   ...

  9. hadoop 2.5.2源码编译

    编译过程漫长无比,错误百出,需要耐心耐心!! 1.准备的环境及软件 操作系统:Centos6.4 64位 jdk:jdk-7u80-linux-x64.rpm,不要使用1.8 maven:apache ...

  10. Express中间件body-parser

    在http请求种,POST.PUT.PATCH三种请求方法中包含着请求体,也就是所谓的request,在Nodejs原生的http模块中,请求体是要基于流的方式来接受和解析. body-parser是 ...