D - Yet Another Palindrome Partitioning
Time limit : 3sec / Memory limit : 512MB
Score : 700 points
Problem Statement
We have a string s consisting of lowercase English letters. Snuke is partitioning s into some number of non-empty substrings. Let the subtrings obtained be s1, s2, …, sN from left to right. (Here, s=s1+s2+…+sN holds.) Snuke wants to satisfy the following condition:
- For each i (1≤i≤N), it is possible to permute the characters in si and obtain a palindrome.
Find the minimum possible value of N when the partition satisfies the condition.
Constraints
- 1≤|s|≤2×105
- s consists of lowercase English letters.
Input
Input is given from Standard Input in the following format:
s
Output
Print the minimum possible value of N when the partition satisfies the condition.
Sample Input 1
aabxyyzz
Sample Output 1
2
The solution is to partition s as aabxyyzz
= aab
+ xyyzz
. Here, aab
can be permuted to form a palindrome aba
, and xyyzz
can be permuted to form a palindrome zyxyz
.
Sample Input 2
byebye
Sample Output 2
1
byebye
can be permuted to form a palindrome byeeyb
.
Sample Input 3
abcdefghijklmnopqrstuvwxyz
Sample Output 3
26
Sample Input 4
abcabcxabcx
Sample Output 4
3
The solution is to partition s as abcabcxabcx
= a
+ b
+ cabcxabcx
.
将26个字母状压到每个二进制位上
则一个字符串能变成回文串当且仅当它每个字符的异或和为0或2^j
f[i]表示到i位最少分成几个回文串
sum[i]表示异或的前缀和
则f[i]=min{f[j]}+1(sum[i]^sum[j]==0或2^k)
由于后面的关系满足减法性质?即可以从sum[i]和枚举k找到sum[j]
所以我们记g[i]表示状态为i的时候的最小f值
就可以O(26n)的dp了
空间是2^26的
#include<cstdio>
#include<cstring>
const int N=2e5+7;
char a[N];
int sum[N];
int f[N];
int g[(1<<26)];
inline int min(int a,int b)
{
return a<b?a:b;
}
int main()
{
scanf("%s",a+1);
int len=strlen(a+1);
for(int i=1;i<=len;i++) sum[i]=sum[i-1]^(1<< (a[i]-'a') );
memset(f,127,sizeof(f));
memset(g,127,sizeof(g));
g[0]=0;
for(int i=1;i<=len;i++)
{
f[i]=min(f[i],g[sum[i]]+1);
for(int j=0;j<=25;j++)
f[i]=min(f[i],g[sum[i]^(1<<j)]+1);
g[sum[i]]=min(g[sum[i]],f[i]);
}
printf("%d\n",f[len]);
return 0;
}