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

【Atcoder】CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning

时间:2017-11-04 17:54:54      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:ems   空间   space   c++   str   size   快速   最小   out   

【题意】

给定只含小写字母的字符串,要求分割成若干段使段内字母重组顺序后能得到回文串,求最少分割段数。n<=2*10^5

【题解】

关键在于快速判断一个字符子串是否合法,容易发现合法仅当不存在或只存在一个奇数字符,其余字符均为偶数。

当涉及到奇偶性(%2)时,很自然能想到异或。

将小写字母a~z转化2^0~2^25,那么一个字符子串合法当且仅当其连续异或值是0或2^i(0<=i<=25)

令f[i]表示前i个合法的最少段数,sum[i]表示异或前缀和,则有:

f[i]=min(f[j])+1,sum[i]^sum[j]=0||2^i,也就是在前面所有合法的j中取最小的f[j]。

将合法条件移项,得到sum[i]^(0||2^i)=sum[j],那么对于当前的i,可以快速算出需要的sum[j]。

而sum值只有2*10^5个,可以用map存起来,然后就可以快速取用。

或者sum值本身不大,根据题目空间直接开数组也没问题。

复杂度O(26*n)。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 50;
char a[maxn];
int f[maxn], sum[1 << 26];
int main(){
	scanf("%s", a + 1); int n = strlen(a + 1);
	memset(sum, 0x3f, sizeof(sum));
	int g = 0;
	f[0] = 0; sum[0] = 0;
	for (int i = 1; i <= n; ++i){
		int x = 1 << (a[i] - ‘a‘);
		g ^= x;
		f[i] = sum[g];
		for (int j = 0; j < 26; ++j) f[i] = min(sum[g ^ (1 << j)], f[i]);
		++ f[i];
		sum[g] = min(sum[g], f[i]);
	}
	cout << f[n] << endl;
	return 0;
}

【Atcoder】CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning

标签:ems   空间   space   c++   str   size   快速   最小   out   

原文地址:http://www.cnblogs.com/juruohx/p/7783677.html

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