IOI 回文词(最长公共子序列)

回文词(IOI)

Time Limit:6000MS  Memory Limit:565536K
Total Submit:253 Accepted:97

Description

回文词是一种对称的字符串——也就是说,一个回文词,从左到右读和从右到左读得到的结果是一样的。任意给定一个字符串,通过插入若干字符,都可以变成一个回文词。你的任务是写一个程序,求出将给定字符串变成回文词所需插入的最少字符数。 
  比如字符串“Ab3bd”,在插入两个字符后可以变成一个回文词(“dAb3bAd”或“Adb3bdA”)。然而,插入两个以下的字符无法使它变成一个回文词。 

Input

第一行包含一个整数N,表示给定字符串的长度,3<=N<=5000 
  第二行是一个长度为N的字符串,字符串由大小写字母和数字构成。 

Output

一个整数,表示需要插入的最少字符数。

Sample Input

5
Ab3bd

Sample Output

2

Source

IOI 2000 



题目大意:

给你一个字符串,然后让你求出最少加多少个字符就能构成一个回文串。

解题思路:

首先把这个字符串进行反串,然后求原串和反串的最长公共子序列,求出来后,用串长减去最长公共子序列的长度就是答案了。

至于为什么答案会是这样?其实,也是很好想的,我们有一个串比如说“Ab3bd”那么他的反串就是“db3bA”,最长的公共子序列就是b3b。

那么,这样一来剩下了A和d,所以呢,有两个字符不同,那么一定是给左右各配置一个不同的字符,才能满足其成为一个回文串。


代码:

# include<cstdio>
# include<iostream>
# include<algorithm>
# include<cstring>
# include<string>
# include<cmath>
# include<queue>
# include<stack>
# include<set>
# include<map>

using namespace std;

# define inf 999999999
# define MAX 5000+4

int n;
char s1[MAX];
char s2[MAX];
int dp[MAX][MAX];

void solve()
{
    for ( int i = 1;i <= n;i++ )
    {
        for ( int j = 1;j <= n;j++ )
        {
            if ( s1[i] == s2[j] )
            {
                dp[i][j] = dp[i-1][j-1]+1;
            }
            else
            {
                dp[i][j] = max( dp[i-1][j],dp[i][j-1] );
            }
        }
    }
}

int main(void)
{
    while ( cin>>n )
    {
        cin>>s1+1;// s1从1开始输入
        for ( int i = 1;i <= n;i++ )
        {
            s2[i] = s1[n+1-i];
        }
        solve();
        cout<<n-dp[n][n]<<endl;

    }


	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值