poj1159_dp

题目描述:

   回文串定义:正向和反向的串是一样的。给出一个串,求问需要最少插入多少个字符才能变成一个回文串。

 

解题思路:

   要找回文串需要插入的字符个数,就是选择某个空隙或者位置对折后看最大匹配的字符个数,不匹配的部分就是要插入的字符数了。

   那么也就是说可以转换为求:倒过来和正过来比,找下最长相似串的长度,用总长度减去匹配的就是要插入的。比如说一个字符数为9的串,正着和倒着找到5个次序上相同的串。那么就是剩下的4个字符需要被补全。所以要插入的就是4.

   那么现在的问题就是:如何找到两个字符串的,按照次序能匹配的最长的串呢?

   令dp[i]=j表示匹配了i个字符时,最靠前的相对原字符串的索引下标j。【记录最靠前是为了让后面可匹配的长度更长一些】。通过遍历invert串来更新匹配dp[]。然后更新dp[i]->dp[1]。注意更新dp数组的内层循环,检查是否能被更新是判断是不是比原先的dp[]记录的索引靠前即可,如果遍历整个数组就会超时。

 

—— 诶呀,据队友说是典型的最长公共子串的问题。。。。好吧,回头看下。。。

 

代码:

#include
#include
#define N 5001

char input[N], invert_input[N];
int dp[N], dp_index=0, len;//dp[i]=j 表示匹配i个字符的最小索引位置。dp[0]=0;

main(){
   int i, j, k;
   
   scanf("%d",&len);
   scanf("%s",input);
  
   for(i=len-1;i>=0;i--){
      invert_input[len-i-1] = input[i];
      dp[i] = len;
   }
   dp[len] = len;// 1->len !!!!!
   dp[0] = -1;
  
   for(i=0;i
      for(j=dp_index+1;j>0;j--){ // update dp[j]->dp[1]
         for(k=dp[j-1]+1;k
            if( input[k] == invert_input[i] ){
               dp[j] = k;
               //printf("update dp[%d] = %d\n",j,dp[j]);
               break;
            }
         }
      }
      if(dp[dp_index+1]!=len){ 
         dp_index++;
      }
   }
  
   printf("%d\n", len - dp_index);

   system("pause");
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值