2017网络新生赛2303回文字串心得
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017网络新生赛2303回文字串心得相关的知识,希望对你有一定的参考价值。
题目描述:
回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。
比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。
注:此问题区分大小写.
输入描述:
一个字符串(0<strlen<=1000)
输出描述:
有且只有一个整数,即最少插入字符数
输入样例:
Ab3bd
输出样例:
2
分析:
这是一道有关于DP的LCS问题,也就是最长公共子序列问题。
我们先看网上的一种动规方程解出的代码,这个代码我还没有完全想通,所以暂时先上代码,希望大家能尽量去理解这个动规方程。
代码:
#include <stdio.h>
#include <string.h>
int a1[1000][1000];
int min1(int a,int b)
{
return a < b ? a : b;
}
int main(void)
{
int i,j,p;
char c[1001];
scanf ("%s",c);
p = strlen(c);
memset(a1,0,sizeof(a1));
for (i = p - 1; i >= 0; i--)
{
for (j = i + 1; j < p; j++)
{
if(c[i] == c[j])
{
a1[i][j] = a1[i + 1][j - 1];
}
else
{
a1[i][j] = min1(a1[i + 1][j],a1[i][j - 1]) + 1;
}
printf("%d ",a1[i][j]);
}
printf("\n");
}
printf ("%d\n",a1[0][p - 1]);
return 0;
}
解法2:
DPLCS解法。
所谓的LCS,就是指两个字符串的最长公共子序列,比如说,Ab3bd和Abbd的最长公共子序列就是Abbd,它的长度是4,也就是说,一个字符串的子序列是可以忽略该字符串的任意一个或者多个字符的。
而对于这道题目,为了使该字符串成为一个回文串,我们需要做的是:将该字符串和它的反串进行最长子序列长度的查找。DP方程是:当c1[i] == c2[j]时,a[i][j] = a[i - 1][j - 1] + 1;否则 a[i][j] = max1(a[i - 1][j],a[i][j - 1]);
求完二维数组以后,a[p - 1][p - 1]就是该字符串和其反串最长公共子序列的长度.用p减去a[p - 1][p - 1]就是使之成为回文串所需插入的最少字符数。因为,只有除了最长公共子序列以外的字符,需要通过插入字符来使之成为回文串,从而导致整体为回文串,而我们只需要插入与除最长公共子序列以外的字符数,就能使这些字符成为回文串,从而整体成为回文串。下面上代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
int n;
int dp[1001][1001];
char str1[1001],str2[1001];
int main()
{
scanf("%s", str1+1);
n = strlen(str1+1);
for(int i = 1; i <= n; i++)
str2[i] = str1[n-i+1]; //做一个逆序的字符串数组
for(int i = 1; i<=n; i++)
for(int j = 1; j <= n; j++)
if(str1[i] == str2[j])
dp[i][j] = dp[i-1][j-1] + 1; //最长公共自序列匹配
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]); //不匹配的往下匹配状态
printf("%d\n", n-dp[n][n]); //字符串长度减去匹配出的最长公共自序列的值
return 0; //即需要添加的字符数
}
以上是关于2017网络新生赛2303回文字串心得的主要内容,如果未能解决你的问题,请参考以下文章