您的位置:首页 > 其它

uva10617

2016-02-29 19:36 211 查看
题目大意:

问有几种删除字符的方法可以使得该字符串为回文。

思路:

记忆化搜索。

状态转移方程:

if(s[i] == s[j]) , 那么 dp[i][j] = dp[i + 1][j] + dp[i][ j - 1] - dp[i + 1][j - 1] + dp[i + 1][j - 1] + 1;

dp[i][j]表示的是从i到j最多可以有几个不同的回文串。 回文串不同那么自然删除的方法就不一样了。

dp[i][j] 是由 i + 1到j的回文串数和i到j - 1的回文串数组成的,然而中间的i + 1到j - 1的回文串多算了一次 因此要减去,但是s[i] == s[j]的时候,i + 1 到j - 1的每个回文串都可以与 s[i],s[j]组成一个新的回文串,因此要加上dp[i + 1][j - 1] + 1。

if(s[i] != s[j]) 那么dp[i][j] = dp[i + 1][j] + dp[i][ j - 1] - dp[i + 1][j - 1];

代码:

#include <iostream>
using namespace std;
#include <stdio.h>
#include <cstring>

char s[65];
long long dp[105][105];
bool vis[105][105];
long long d(int i,int j) {
long long & ans = dp[i][j];
if(vis[i][j]) return ans;
vis[i][j] = 1;
if(i > j) ans = 0;
else if(i == j) ans = 1;
else if(s[i] == s[j]) {
ans = d(i,j - 1) + d(i + 1,j) + 1;
}
else {
ans = d(i,j - 1) + d(i + 1, j) - d(i + 1, j - 1);
}
return ans;
}
int main() {
int n;
scanf("%d",&n);
getchar();
while(n--) {
gets(s);
int len =strlen(s);
for(int i = 0;i < len; i++)
dp[i][i] = 1;
memset(vis,0,sizeof(vis));
long long ans = d(0,len - 1);
/*      for(int i = len - 1; i >= 0; i--) {
for(int j = i + 1; j < len; j++) {
if(s[i] == s[j])
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] + 1;
else {
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1];
if(ans < dp[i][j])
ans = dp[i][j];
}
}
}*/
printf("%lld\n",ans);
}
return 0;
}
第二种:
#include <iostream>
using namespace std;
#include <stdio.h>
#include <cstring>

char s[65];
long long dp[105][105];
bool vis[105][105];

/*long long d(int i,int j) {
long long & ans = dp[i][j];
if(vis[i][j]) return ans;
vis[i][j] = 1;
if(i > j) ans = 0;
else if(i == j) ans = 1;
else if(s[i] == s[j]) {
ans = d(i,j - 1) + d(i + 1,j) + 1;
}
else {
ans = d(i,j - 1) + d(i + 1, j) - d(i + 1, j - 1);
}
return ans;
}*/
int main() {
int n;
scanf("%d",&n);
getchar();
while(n--) {
gets(s);
int len =strlen(s);
for(int i = 0;i < len; i++)
dp[i][i] = 1;
memset(vis,0,sizeof(vis));
//  long long ans = d(0,len - 1);
//      long long ans = 0;
for(int i = len - 1; i >= 0; i--) {
for(int j = i + 1; j < len; j++) {
if(s[i] == s[j])
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] + 1;
else {
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1];
//          if(ans < dp[i][j])
//              ans = dp[i][j];
}
}
}
printf("%lld\n",dp[0][len - 1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: