码迷,mamicode.com
首页 > 其他好文 > 详细

[codeforces1234F]Yet Another Substring Reverse

时间:2019-10-04 21:24:08      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:处理   memset   span   its   tar   long   相同   sizeof   audio   

题目链接

大致题意为将某个子串进行翻转后,使得不包含相同字符的字符子串长度最长。只能翻转一次或零次。

设一个子串的状态为包含字符的二进制。如子串为$abacd$,则状态为$00000000000000001111$。

根据分析可以得到,一个子串和另一个子串如果没有交集,则两个串可以经过一次翻转合并在一起。

例如:$abcdefga$,串$ab$和串$fg$,可以通过翻转$cdefg$变成$abgfedca$。

所以如果枚举一个状态,再枚举这个状态的补集的子集。就可以得到合法的状态。

但是枚举子集的复杂度太大,所以我们先处理出每种合法状态有多少个字符,然后再从小到大枚举一遍状态。这样可以得到每种状态的合法子集的最大值。

然后计算答案。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1e5 + 100;
 5 int dp[1 << 21], vis[21];
 6 string s;
 7 int main() {
 8     cin >> s;
 9     for (int i = 0; i < s.size(); i++) {
10         int mark = 0, cnt = 0;
11         memset(vis, 0, sizeof(vis));
12         for (int j = i; j < s.size(); j++) {
13             if (vis[s[j] - a])
14                 break;
15             vis[s[j] - a] = 1;
16             mark |= (1 << (s[j] - a));
17             cnt++;
18             dp[mark] = cnt;
19         }
20     }
21     for (int i = 0; i < (1 << 20); i++)
22         for (int j = 0; j < 20; j++)
23             if (i & (1 << j))
24                 dp[i] = max(dp[i], dp[i ^ (1 << j)]);
25     int ans = 0;
26     for (int i = 0; i < (1 << 20); i++)
27         ans = max(ans, dp[i] + dp[i ^ ((1 << 20) - 1)]);
28     printf("%d\n", ans);
29 }

 

[codeforces1234F]Yet Another Substring Reverse

标签:处理   memset   span   its   tar   long   相同   sizeof   audio   

原文地址:https://www.cnblogs.com/sainsist/p/11622922.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!