nyoj17_单调递增最长子序列

原题链接》》》

参考了这位大兄弟的blog才弄懂》》》


一.第一种解法
运行时间内存 : 316 248

描述:s[i]为输入字符串
dp[i]表示第i为之前,并且s[i]作为最大字符存在的单调递增子序列的长度。例如:s="abklmncdefg";
dp[0]=1(初始值)
dp[1]=2 b最大
dp[2]=3 k作为最大时
dp[3]=4
dp[4]=5
dp[5]=6
dp[6]=3 c作为最大时 abc的长度为3
dp[7]=4
dp[8]=5
dp[9]=6
dp[10]=7

最后一步求dp数组的最大值,即为dp[10]=7;

#include<stdio.h>
#include<string.h>
char s[10001];
int main(){
    int N;
    int dp[10001];
    scanf("%d",&N);
    while(N--){
        scanf("%s",s);
        memset(dp,0,sizeof(dp));
        int len=strlen(s);
        int max;
        dp[0]=1;
        for(int i=1;i<len;i++){
            max=0;
            for(int j=i-1;j>=0;j--){
                if(s[i]>s[j]&&max<dp[j]){
                    max=dp[j];
                }
            }
            dp[i]=max+1;
        }
        max=dp[0];
        for(int i=1;i<len;i++)
            if(max<dp[i])
                max=dp[i];
        printf("%d\n",max);
    }
    return 0;
} 

第二种解法:
感觉运行速度贼快 时间,内存: 4 256

#include<stdio.h>
#include<string.h>
#define N 10010
char s[N];
char ans[N];
int count;

int main()
{
    int test,len,i,j;
    scanf("%d",&test);
    while(test--)
    {
        scanf("%s",s);
        len=strlen(s);
        count=1;
        ans[0]=s[0];
        for(i=0;i<len;i++)
        {
            for(j=count-1;j>=0;j--)
            {
                if(j==0&&ans[0]>s[i]) ans[0]=s[i];
                if(ans[j]<s[i])
                {
                    ans[j+1]=s[i];
                    if(j==count-1)  count++;
                    break;
                }
            }
        }
        ans[count]='\0';
        printf("%d\n",count);
    }
    return 0;
}

第三种时间复杂度为nlogn的解法:

#include<stdio.h>
#include<string.h>
char str[10001];
char ans[10001];
int len;
//二分查找
int Find_2(int i){
    int l,r,m;
    l=0;r=len-1;
    while(l<r){
        m=l+(r-l)/2;
        if(ans[m]>=str[i]) r=m;
        else l=m+1;
    }
    return l;
}
int main(){
    int N,t;
    scanf("%d",&N);
    while(N--){
        scanf("%s",str);
        len=1;
        t=strlen(str);
        ans[0]=str[0];
        for(int i=1;i<t;i++){
            if(ans[len-1]<str[i])
                ans[len++]=str[i];
            else{
                int pos=Find_2(i);
                ans[pos]=str[i];
            }
        }
        printf("%d\n",len);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值