这两道题目均是求最长公共子序列,只是36题说得更明白些,37题的思路:求原字符串和其逆序的最长公共子序列。
利用动态规划求最长公共子序列,状态转移方程为:
if(str1[i]==str2[i]) then f[m][n]=f[m-1][n-1]+1
else f[m][n]=max{f[m-1][n],f[m][n-1]}
f[m][n]表示的意思是str1数组的前m个元素与str2数组的前n个元素的最长公共子序列的长度
NYOJ36代码:
#include<stdio.h>
#include<string.h>
const int MAX=1001;
char str1[MAX];
char str2[MAX];
int fun[MAX][MAX];
int main()
{
// freopen("in.txt","r",stdin);
int n;
scanf("%d",&n);
while(n&&n--)
{
scanf("%s%s",&str1,&str2);
int len1=strlen(str1);
int len2=strlen(str2);
for(int i=0;i<len1;++i) //注意若将此处写成strlen()函数调用,会超时
{
for(int j=0;j<len2;++j)
{
if(str1[i]==str2[j])
{
fun[i+1][j+1]=fun[i][j]+1;
}
else
{
fun[i+1][j+1]=(fun[i+1][j]>fun[i][j+1]?fun[i+1][j]:fun[i][j+1]);
}
}
}
printf("%d\n",fun[len1][len2]);
}
}
NYOJ37代码:
#include<stdio.h>
#include<string.h>
const int MAX=1001;
char str1[MAX];
char str2[MAX];
int fun[MAX][MAX];
int main()
{
//freopen("in.txt","r",stdin);
int n;
scanf("%d",&n);
while(n&&n--)
{
scanf("%s",&str1);
int len1=strlen(str1);
for(int i=len1-1;i>=0;i--)
{
str2[len1-i-1]=str1[i];
}
//求最长子序列
for(int i=0;i<len1;++i)
{
for(int j=0;j<len1;++j)
{
if(str1[i]==str2[j])
fun[i+1][j+1]=fun[i][j]+1;
else
fun[i+1][j+1]=(fun[i+1][j]>fun[i][j+1]?fun[i+1][j]:fun[i][j+1]);
}
}
printf("%d\n",len1-fun[len1][len1]);
}
}