您的位置:首页 > Web前端

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

2017-10-22 22:34 501 查看
传送门

D - Yet Another Palindrome Partitioning

题意:给你一个字符串,问最少可以划分成多少段使每一段各自都可以通过一些移动变成回文串。

思路:dp[i]表示到当前的位置最少需要划分的次数,num[i]表示当前为i时最少的dp[i].

用每一个二进制位代表每一个字符,经典的状压dp题。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
char str[MAXN];
int num[1<<26];
int dp[MAXN];
int sum;
int main()
{
scanf("%s", str);
memset(num, 0x3f, sizeof(num));
memset(dp, 0x3f, sizeof(dp));
num[0]=0;
sum=0;
int len=strlen(str);
for(int i=0;i<len;++i)
{
int x=1<<(str[i]-'a');
sum^=x;
dp[i]=min(dp[i], num[sum]+1);
for(int j=0;j<26;++j)
dp[i]=min(dp[i], num[sum^(1<<j)]+1);
num[sum]=min(num[sum], dp[i]);
}
printf("%d\n", dp[len-1]);
return 0;
}


这个hash拉链法值得学习一波。

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<assert.h>
#include<math.h>
#include<algorithm>
//#include<iostream>
using namespace std;

int n;
#define maxn 1000007
struct Hash
{
int first[maxn],Next[maxn],list[maxn],Min[maxn],len;
Hash() {memset(first,0,sizeof(first));len=0;}
int hash(int x) {return x%maxn;}
void insert(int x,int val)
{
int v=hash(x);
for (int i=first[v];i;i=Next[i])
if (list[i]==x) {Min[i]=min(Min[i],val);return;}
len++;
list[len]=x;
Min[len]=val;
Next[len]=first[v];
first[v]=len;
}
int get(int x)
{
int v=hash(x);
for (int i=first[v];i;i=Next[i])
if (list[i]==x) return Min[i];
return 0x3f3f3f3f;
}
}h;
char s[maxn];
int f[maxn];
int main()
{
scanf("%s",s+1);n=strlen(s+1);
h.insert(0,0);int now=0;
for (int i=1;i<=n;i++)
{
now^=1<<(s[i]-'a');f[i]=h.get(now)+1;
for (int j=0;j<26;j++)
f[i]=min(f[i],1+h.get(now^(1<<j)));
h.insert(now,f[i]);
}
printf("%d\n",f
);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: