You are given a string s of length n consisting of lowercase Latin letters. You may apply some operations to this string: in one operation you can delete some contiguous substring of this string, if all letters in the substring you delete are equal. For example, after deleting substring bbbb from string abbbbaccdd we get the string aaccdd.
Calculate the minimum number of operations to delete the whole string s.
Input
The first line contains one integer n
(1≤n≤500) — the length of string s.
The second line contains the string s(|s|=n) consisting of lowercase Latin letters.
Output
Output a single integer — the minimal number of operation to delete string s.
Examples
Input
5
abaca
Output
3
Input
8
abcddcba
Output
4
给出一个字符串,每次只能删除一组相邻且相同的字母,求最少几次能把这个字符串全部删除完。
那么对于给出的字符串,我们可以进行相邻位置上的去重。得到一个新的字符串,再对这个字符串处理。
记数组dp[i][j]表示从原字符串中取出[i,j]的子串,最少删除几次能全部删完。
那么对于一个子串[i,j],仅考虑第i位的操作,那么有
- 独立的将s[i]删除
此时有状态转移方程dp[i][j]=min(dp[i][j],dp[i+1][j]+1) - 将s[i]与s[k]一并删除,其中s[k]==s[i]
在这里要从区间[i,j]找出所有的k,满足s[i]==s[k],并有状态转移方程dp[i][j]=min(dp[i][j],dp[i+1,k-1]+dp[k][j])
在使用这种记录区间的dp时,要注意数组的定义,根据定义确认状态转移方程中,是否有元素重复相加或者有元素没有加入。一般记录时用一个半开半闭区间[i,j+1)表示区间[i,j]。
根据状态转移方程,我们发现如果想要求出区间[i,j],就要先求出所有的区间[i+1,k-1] 和 [k,j]。也就是先从大区间[1,n]再到最小不可分割单位[i,i],得到结果后向上返回得到[1,n]的答案。所以在这里选择记忆化搜索实现这个dp。
#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
string s;
int dp[505][505];
map<Pair,int> section;
int dfs(int left,int right);
int main(){
ios::sync_with_stdio(false);
int N,len=0;
cin>>N;
char c;
s+='0';
rep(i,1,N+1){
cin>>c;
if(c != *(s.end()-1)){
len++;
s+=c;
}
}
mem(dp,0);
rep(i,1,len+1){
dp[i][i]=1;
}
cout<<dfs(1,len)<<endl;
re 0;
}
int dfs(int left,int right){
if(dp[left][right]!=0){
;
}else{
int minn=INT_MAX;
minn=min(minn,dfs(left+1,right)+1);
rep(i,left+2,right+1){
if(s[i]==s[left])
minn=min(minn,dfs(left+1,i-1)+dfs(i,right));
}
dp[left][right]=minn;
}
re dp[left][right];
}