题目链接:传送门

思路:

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

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

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

题目中反复强调,给出的字符串只有前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. python数据类型之可hash,不可hash

    可变类型的数据不可哈希,如list,字典:同值不同址,不同值同址   列表,字典可变, 数值.字母.字符串.数字.元组不可变:同值同址,不同值不同址 怎么判断可变不可变 ?   总结:改个值 看id是 ...

  2. kubernetes master 更换ip(单节点)

    问题分析 master ip地址变更以后,我们首先应该检查以下内容: /etc/kubernetes/manifests下面的config配置文件,替换里面对应的ip 相关的证书文件 客户端文件 解决 ...

  3. 添加tomcat为启动服务/删除tomcat服务

    在很多生产把环境下,tomcat的启动要随着windows的启动一起启动,这个时候就需要将tomcat添加成服务.步骤如下: 1:环境配置 配置jdk环境变量: JAVA_HOME:jdk路径 配置p ...

  4. java基础--单例模式的7种实现【转载】

    转载:http://www.blogjava.net/kenzhh/archive/2013/03/15/357824.html 第一种,线程不安全(懒汉模式) 1 public class Sing ...

  5. python - 代码调试的好帮手sys._getframe()

    python 的调试,令人非常忧伤,通过将输出路径打印的方式,可以提高很大的方便性: import sys #coding=utf-8 def get_cur_info(): print sys._g ...

  6. Git - 对一组仓库进行配置

    对一组仓库使用一套配置,另一组仓库使用另一套配置的需求也是有的,比如公司仓库的配置和我个人项目的仓库配置并不完全相同,每次都修改单个仓库的配置太麻烦并且可能会粗心忘改了以错误的配置进行提交,如何对一个 ...

  7. hibernate中get和load区别

    在日常开发中,获取数据时必不可少的,这样就要用到get和load方法来实现了.下面简单说一下get和load的区别. 1.返回值不同 使用get方法检索数据时,没有该数据返回值为null. 而使用lo ...

  8. 阶段3 1.Mybatis_07.Mybatis的连接池及事务_5 mybatis中使用poolead配置连接的原理分析

    idelConnection是空闲的链接 idelConnection就是ArrayList的数组 如果没有空闲的就new一个 新的connection 一个空闲池,一个活动的池,一个链接过来.空闲池 ...

  9. 【Hibernate】---【注解】一对多

    一.核心配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-con ...

  10. cocos2dx基础篇(9) 滑块控件CCControlSlider

    [3.x] (1)去掉 “CC” (2)对象类 CCObject 改为 Ref (3)CCControlEvent 改为强枚举 Control::EventType (4)CCControlEvent ...