您的位置:首页 > 其它

ACM: 回文串 dp题 poj 1159  (滚动…

2016-05-19 23:18 483 查看
 

                                                         
Palindrome

Description

A palindrome is a symmetrical string, that is,
a string read identically from left to right as well as from right
to left. You are to write a program which, given a string,
determines the minimal number of characters to be inserted into the
string in order to obtain a palindrome.

As an example, by inserting 2 characters, the
string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or
"Adb3bdA"). However, inserting fewer than 2 characters does not
produce a palindrome.

Input

Your program is to read from standard input.
The first line contains one integer: the length of the input string
N, 3 <= N <= 5000. The second line
contains one string with length N. The string is formed from
uppercase letters from 'A' to 'Z', lowercase letters from 'a' to
'z' and digits from '0' to '9'. Uppercase and lowercase letters are
to be considered distinct.

Output

Your program is to write to standard output.
The first line contains one integer, which is the desired minimal
number.

Sample Input

5

Ab3bd

Sample Output

2

题意: 给你一个字符串,计算最少插入多少个字母形成回文串.

解题思路:

              
1. dp题肯定先找出状态转移方程. 一开始想把串分成两部分找最长相同字串.

              
2. 但是发现并不是同时两个字串都要添加字母,每次只是添加一个就行.

              
3. 状态转移方程: 设dp[i][j]是第i到第j字符需要至少添加多少个字符形成回文串.

                   
即: if(str[i] == str[j]) dp[i][j] =
dp[i+1][j-1];   (i = n-1
>> i = 1;)  (j = i+1
>> j = n)

                        
else dp[i][j] = min(dp[i+1][j] , dp[i][j-1]) + 1;

              
4. 郁闷的是发现5000的二位数组开不下.T.T.网上看见讨论用.short型.还好暴力AC.

              
5. 还发现大牛们的是滚动数组. 每次只需e = 1-e;变换即可. 学习学习.

代码1:

#include
<cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 5005

int n;

char str[MAX];

short dp[MAX][MAX];

inline int min(int a,int b)

{

    return a
> b ? a : b;

}

int main()

{

//  
 freopen("input.txt","r",stdin);

  
 while(scanf("%d",&n) !=
EOF)

    {

  
   
 getchar();

  
   
 int i, j;

  
   
 for(i = n; i >= 1; --i)

  
   
   
 scanf("%c",&str[i]);

  
   
 str[i] = '\0';

  
   
 memset(dp,0,sizeof(dp));

  
   
 

  
   
 for(int i = n-1; i >= 1;
--i)

  
   
 {

  
   
   
 for(int j = i+1; j <= n;
++j)

  
   
   
 {

  
   
   
   
 if(str[i] == str[j])

  
   
   
   
   
 dp[i][j] = dp[i+1][j-1];

  
   
   
   
 else

  
   
   
   
   
 dp[i][j] = min(dp[i+1][j],dp[i][j-1])+1;

  
   
   
 }

  
   
 }

  
   
 printf("%d\n",dp[1]
);

    }

    return
0;

}

代码2:

#include
<cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 5005

int n;

char str1[MAX], str2[MAX];

int dp[2][MAX];

inline int max(int a,int b)

{

    return a
> b ? a : b;

}

int main()

{

//  
 freopen("input.txt","r",stdin);

  
 while(scanf("%d",&n) !=
EOF)

    {

  
    
getchar();

  
    
for(int i = 1; i <= n; ++i)

  
    
   
scanf("%c",&str1[i]);

  
    
str1[n+1] = '\0';

  
    
for(int i = 1; i <= n; ++i)

  
    
    str2[i] =
str1[n-i+1];

  
    
str2[n+1] = '\0';

  
    

  
    
memset(dp,0,sizeof(dp));

  
    
int e = 0;

  
    
for(int i = 1; i <= n; ++i)

  
    
{

  
    
    e =
1^e;

  
    
    for(int j =
1; j <= n; ++j)

  
    
    {

  
    
   
    if(str1[i]
== str2[j])

  
    
   
   
    dp[e][j] =
dp[1^e][j-1] + 1;

  
    
   
    else

  
    
   
   
    dp[e][j] =
max(dp[e][j-1],dp[1^e][j]);

  
    
    }

  
    
}

  
    
printf("%d\n",n-dp[1^e]
);

    }

    return
0;

}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: