水题吧,记忆化搜索即可
回文字符串
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba"。当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串。现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串。
-
输入
-
第一行给出整数N(0<N<100)
接下来的N行,每行一个字符串,每个字符串长度不超过1000.
输出
- 每行输出所需添加的最少字符数 样例输入
-
1 Ab3bd
样例输出
-
2
来源
- IOI 2000
-
第一行给出整数N(0<N<100)
/****************************************
* author:crazy_石头
* pro:回文字符串-区间dp
* date:2014/04/16
* algorithm: dp
* 思路: 区间dp固定模式:
* 考虑i~j区间的字符串;
* 1.是一个字符的话回文,添加字符数量为0;
* 2.是两个字符并且相等的话也是回文的,添加字符数量为0;
* 3.一般情况,就是考虑第i个字符,如果第j个字符处的字符与它不相等的话,
*那么把第i个字符和后面的串隔离开,给第i个字符单独添加一个字符,即:
* dp[i][j]=dp[i+1][j]+1;(dp[i+1][j]是隔离开的串,加的1就是给dii个字符加的
* 所以dp[i][j]=std::min(dfs(i+1,j)+1,dfs(i,j-1)+1);看懂了吧?
*****************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std; #define INF INT_MAX #define eps 1e-8 #define A system("pause") #define rep(i,h,n) for(int i=(h);i<=(n);i++) #define ms(a,b) memset((a),(b),sizeof(a)) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define mod 1e9+7 #define LL long long const int maxn=1000+5; char ch[maxn]; int d[maxn][maxn]; inline int dfs(int i,int j) { if(~d[i][j]) return d[i][j]; if(i==j) return d[i][j]=0; if(ch[i]==ch[j]&&i+1==j)//是回文双字符,无需添加字符 return d[i][j]=0; if(ch[i]==ch[j]) return d[i][j]=dfs(i+1,j-1);//匹配的话不管最外层括号,相当于往近了一层; d[i][j]=std::min(dfs(i+1,j)+1,dfs(i,j-1)+1); return d[i][j]; } int main() { int n; scanf("%d",&n); while(n--) { scanf("%s",ch); ms(d,-1); int len=strlen(ch); int ans=dfs(0,len-1); printf("%d\n",ans); } return 0; }