2016,4,2 16:03
题目:
单调递增最长子序列
时间限制:3000 ms | 内存限制:65535 KB
难度:4
-
描述
- 求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4-
输入
- 第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000
输出 - 输出字符串的最长递增子序列的长度 样例输入
-
3 aaa ababc abklmncdefg
样例输出 -
1 3 7
- 第一行一个整数0<n<20,表示有n个字符串要处理
思想:这道题时间复杂度为o(n2),是LCS(最长公共子序列)的变形。相当于 一个x 原数组,一个y 数组由x 数组 升序排列并去掉重复值,求两个数组的最长公共子序列问题。
代码:
<pre name="code" class="cpp"><span style="font-size:18px;">//注意:二维数组的传递 方式
#include <stdio.h>
#include <string.h>
char x[10001];
char y[10001];
int c[27][10001];
int AscendingLCS(int m,int n )
{
int i,j;
//初始化
for(i=0;i<m;i++)
*((int *)c+i*n+0)=0;
for(j=0;j<n;j++)
*((int *)c+0+j)=0;
//dp: o(n^2)
for(i=1;i<m;i++)
{
for(j=1;j<n;j++)
{
if(x[i-1]==y[j-1])
{
*((int *)c+i*n+j)=*((int *)c+(i-1)*n+j-1)+1;
}
else
{
if(*((int *)c+(i-1)*n+j)>=*((int *)c+i*n+j-1))
{
*((int *)c+i*n+j)=*((int *)c+(i-1)*n+j);
}
else
{
*((int *)c+i*n+j)=*((int *)c+i*n+j-1);
}
}
}
}
//返回最优值 (最优值是手工转变为: *((int*)array + n*i + j);)
return *((int *)c+(m-1)*n+n-1);
}
int main(void)
{
int i,j,min,L=0,k,S;//S行,L列
int m;
scanf("%d",&m);
getchar();
while(m--){
scanf("%s",x);
L=strlen(x);
S=L;
//复制到 y 数组
strcpy(y,x);
//数组排序并去掉重复值
for(i=0;i<L-1;i++)
{
min=i;
for(j=i+1;j<L;j++)
{
if(y[j]<y[min])
{
min=j;
}
}
if(min!=i)
{
int temp=y[min];
y[min]=y[i];
y[i]=temp;
}
}
//排好序去重复值
i=0;
while(i<L-1){
if(y[i+1]==y[i])
{
for(k=i;k<L-1;k++)
{
y[k]=y[k+1];
}
L--;
}
else
i++;
}
printf("%d\n", AscendingLCS(S+1,L+1));
}
return 0;
}
</span>
做题心得:
1.二维数组的传递方式:
对于下面的声明:
int hoge[2][3;]
方式一:void func(int **hoge):则数组元素需经手工运算:*((int*)c + n*i + j);) .
方式二:void func(int (*hoge) [3]),
或是:
void func(int hoge[][3]);
或是:
void func(int hoge[2][3];