POJ部分题

/*最长上升子序列问题 LIS
有一个长为N的数列A0,A1,A2,……An-1
请求出这个序列中最长的上升子序列长度
上升子序列是指的对于任意的i<j 都有Ai<Aj
EG:
输入:N=5
 A={4,2,3,1,5}
 输出3        //<2,3,5>
解 动态规划:
定义DP[i]为以Ai为末尾的最长上升子序列长度
则 DP[i]为
只包含Ai的子序列
或者
在满足子长上升子序列的要求上 追加Ai到末尾得到长度增加的LIS
∴ DP[i]=MAX(1   , DP[j]+1【 i<j&&Ai<Aj 】)
时间复杂度O(N^2)
*/
# include <stdio.h>
# define MAX(a,b) ((a)>(b)?(a):(b))
# define S 100
int main(){
    int A[S]={0},DP[S]={0},sum=1,N,i,j,B[S]={0},k=0;
	scanf("%d",&N);
    for(i=0;i<N;i++)
		scanf("%d",&A[i]);
	for(i=0;i<N;i++)
	{
		DP[i]=1;
	    for(j=0;j<i;j++)
              if(A[j]<A[i])
				  DP[i]=MAX(DP[i],DP[j]+1);
	  sum=MAX(sum,DP[i]);
	}
	printf("%d",sum);
	return 0;
}


说到字符串匹配,这是一个老但是热度不减的话题

也是学数据结构必须要会的

代码--如果不写注释 几乎不会有人看 

虽然是学计算机的  前方的路对我来说还比较迷茫

只能是---》漫天撒网抓蝴蝶---low漏陋

经过半个小时的复习 整理   想着能将代码简洁化 又不失条理

将KMP和BF的写在一起 就当做个比较吧  

这种经典算法 不需要解释 至于将代码简洁化

我想  大概人人都想自己做  而且自己做出来的才有意义  别人做的除非很好 否则很难看的下去  

另外 做的字符串替换  链接:字符串替换-循环

# include <stdio.h>
# include <stdlib.h>
# define N 101 //用户输入的字符串长度最大值为N-1  第N个存'\0'
# define M 2   //用户输入的字符串长度最小值 
int BF(char a[],char b[]);//BF算法 a为主串,b为被检验的串返回匹配的下标 若无返回0
int KMP(char *A,char *B);//比BF复杂度低  和BF功能相同
int gainchar(char *a,int min,int max);//模拟strlen类 对*a输入范围[min,max-1]返回字符串长度,不影响下一级输入
int main(){
	char A[N],B[N];
	int len;
	printf("请输入A字符串(%d---%3d):\n",M,N-1);
	len=gainchar(A,M,N);
    printf("请输入B字符串(%d---%3d):\n",1,len);
	gainchar(B,1,len+1);
    printf("注:匹配失败返回0!\n\n主串:%s\n次串:%s\nBF:匹配的位置:%d\nKMP匹配的位置:%d",A,B,BF(A,B),KMP(A,B));
	return 0;
}
int gainchar(char *a,int min,int max)//对*a输入范围[min,max-1]  防止数组超界 并清除缓冲区
{
	int c,k;
	do{
		c=-1;k=0;
		fgets(a,max,stdin);
		while(a[++c]);
		c=a[c-1]=='\n'&&c<max?c-1:c;
		if(c>=max-1)
			while(getchar()!='\n')
				k++;
			else
				a[c]='\0';
			if(k||c&&(c>max||c<min))//如果用户只输入'\n'则不提示输入错误,否则提示错误
				printf("输入长度有误,请重新输入!\n注:只录入(%d--%d)字节:\n",min,max-1);
	}while(k||c<min);
    return c;
}
int KMP(char *A,char *B)//经典算法  已经简洁化 复杂度 o(strlen(A)+strlen(B))
{                     
	int i=1,j=0,C=-1,*Q=NULL; 
	while(B[++C]); //求主串A的长度
	Q=(int *)calloc(C,sizeof(int));//申请内存存NEXVAL的值
    while(i<C)               //获得模式串的NEXTVAL数组
		if(!j||B[i]==B[j])       
		{
			++j;
			++i;
			Q[i]=(B[i]-B[j]?j:Q[j]);   
		}
		else
			j=Q[j];
		i=j=0;           //开始和主串匹配
		while (A[i]&&B[j])
			if (A[i++]==B[j])
				j++;
			else
				j=Q[j];
	return B[j]?0:i-j+1;    //返回下标值
}
int BF(char a[],char b[])//BF算法 一般o(strlen(A)+strlen(B))  最坏o(strlen(A)*strlen(B))
{                     
	int i=0,j=0; 
	while (a[i]&&b[j])
		if (a[i++]==b[j]) // 如果匹配成功 继续比较后继字
			++j;
		else      //否则 主串回溯
		{
			i-=j;       
			j=0;
		}
	return b[j]?0:i-j+1;  //返回下标 
}

附加小程序:

/*
辗转相除法(拓展欧几里得算法): 复杂度 最差O(log[max(a,b)])
假设gys(a,b) 是计算a,b 的最大公因数的函数‘
设 a/b得到的商和余数 分别为 p q
则 a=b*p +q;
所以 gys(b,q) 即整除a也整除b 所以gys(b,q)整除gys(a,b)
又q=a-b*p               同理可证 gys(a,b)整除gys(b,q)
综上 gys(a,b)=gys(b,q)  即 gys(a,b)=gys(b,a%b)
由于第二个形参是不断地减少的
所以 最终 gys(a,b)-->gys(c,0)  此时的c即为最大公因数
*/
# include <stdio.h>
int gys(int a,int b);//递归算法
int GYS(int m,int n);//非递归算法
int main(){
    int A=45,B=24;
	printf("%d %d的最大公因数\n递归:  %d\n非递归:%d\n",A,B,gys(A,B),GYS(A,B));
	printf("最小公倍数\n递归:  %d\n非递归:%d",A*B/gys(A,B),A*B/GYS(A,B));
    return 0;
}
int gys(int a,int b)//递归算法
{
	return b?gys(b,a%b):a;
}
int GYS(int m,int n)//非递归算法
{
  int A,B;
  if(n>m)
  {
    A=m;m=n;n=A;
  }
  while((B=m%n)!=0)
  {
    m=n;n=B;
  }
  return n;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值