Yet Another Palindrome Partitioning

url

大意:

把一个字符串s分割成m个串,这m个串满足至多有一种字符出现次数为奇数次,其他均为偶数次,问m的最小值

思路:
一开始看错了题意,以为是可以任意重排字符串,然后刷刷敲完之后死活过不去。。。

字符串顺序是不能改变的。那么这里可以用一个状压的思路。用f[i](1到26的一个01串对应的大小)来代表从1到i的每一个字母的数量(奇数为1,偶数为0)

则区间[l, r]可以加一个子串,就是a[l]^a[r]的值必须为2的幂次(也就是中间只有一个奇数次数的字母)。

然后用dp来对每一个状态进行推导。

如果某一状态本身=0,说明里面全是偶数,则其dp值=1;

如果某一个状态只有一位为1,说明里面只有一个奇数,其dp值也应该=1,这一定最优

另外考虑其它状态,就枚举每一位进行转移就好了。

for(int j=0;j<26;++j)
		{
			//cout<<dp[f[i]]<<' '<<dp[f[i]^(1<<j)]<<endl;
			dp[f[i]]=min(dp[f[i]],(ll)dp[f[i]^(1<<j)]+1);
		}

code:

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define endl '\n'
const ll N=2e5+100;
string s;
ll f[N];
ll dp[(1<<26)];//对应状态的最优解 
bool ff(ll x)//对应状态 
{
	if(x==0)
	{
		dp[x]=1;
		return 1;
	}
	for(int i=0;i<26;++i)
	{
		if((x^(1<<i))==0)
		{
			dp[x]=1;
			return 1;
		}
	}
	return 0;
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>s;
    ll ans=0;
    for(int i=0;i<s.size();++i)
    {
    	ans^=(1<<(s[i]-'a'));
    	f[i]=ans;
	}
	//for(int i=0;i<s.size();++i) cout<<f[i]<<' '; 
	memset(dp,0x3f,sizeof dp);
	//dp[0]=0;
	for(int i=0;i<s.size();++i)
	{
		if(ff(f[i])) continue;//判断是否全是偶数
		for(int j=0;j<26;++j)
		{
			//cout<<dp[f[i]]<<' '<<dp[f[i]^(1<<j)]<<endl;
			dp[f[i]]=min(dp[f[i]],(ll)dp[f[i]^(1<<j)]+1);
		}
	}
	cout<<dp[f[s.size()-1]];
	return 0;
 } 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值