最长严格上升子序列

LIS问题,动归时间复杂度o(n2),可以用单调队列优化到o(nlogn)

http://blog.csdn.net/dangwenliang/article/details/5728363

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 int n,dp[5005],orz[5005],ans = 0;
 6 int main(){
 7     cin>>n;
 8     for(int i = 1;i <= n;i++) scanf("%d",&orz[i]);
 9     for(int i = 1;i <= n;i++){
10         dp[i] = 1;
11         for(int j = 1;j < i;j++){
12             if(orz[i] > orz[j])dp[i] = max(dp[i],dp[j]+1);
13             ans = max(ans,dp[i]);
14         }
15     }
16     cout<<ans;
17     return 0;
18 }
View Code
 1 #include <iostream>
 2 using namespace std;
 3 int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n
 4 {
 5     int left=0,right=len,mid=(left+right)/2;
 6     while(left<=right)
 7     {
 8        if(n>a[mid]) left=mid+1;
 9        else if(n<a[mid]) right=mid-1;
10        else return mid;
11        mid=(left+right)/2;
12     }
13     return left;
14 }
15      
16 int main(void)
17 {
18     int n,a[100],c[100],i,j,len;//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标
19     while(cin>>n)
20     {
21         for(i=0;i<n;i++)
22             cin>>a[i];
23         b[0]=1;
24         c[0]=-1;
25         c[1]=a[0];
26         len=1;//此时只有c[1]求出来,最长递增子序列的长度为1.
27         for(i=1;i<n;i++)
28         {
29             j=find(c,len,a[i]);
30             c[j]=a[i];
31             if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1
32                 len=j;//更新len
33         }
34         cout<<len<<endl;
35     }
36     return 0;
37 }
View Code

最长公共子序列

要求c既是a的子序列,又是b的子序列,输出c的长度

设i,j为a到i,b到j可以取到的公共子序列长度,如果当前位置匹配,那么就是两个位置之前能匹配到的+1,如果不能匹配,考虑选一个最长的可能匹配的长度,[i-1][j]和[i][j-1]都是有可能的

for(int i = 1;i <= n;i++){
    for(int j = 1;j <= m;j++){
        dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
        if(a[i] == b[j]) dp[i][j] = max(dp[i][j],dp[i-1][j-1] + 1);
    }
}

最长公共上升子序列

题目在公共子序列的基础上又加了一重上升的限制,可以考虑加一个变量,记录在a[i]的情况下,b[j]小于a[i]的情况下lcis的最大长度,这样,如果发现两个序列对应位置相等,并且已经求出小于a[i]的lcis的长度,就可以直接求出当前位置的了

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
using namespace std;

int max(int a,int b)
{
    return a>b?a:b;
}

int a[3010],b[3010];
int f[3010],n,m;
int LCIS()
{
    int i,j,k;
    memset(f,0,sizeof(f));
    for(i=0;i<n;i++)
    {
        k=0;
        for(j=0;j<m;j++)
        {
            if(a[i]==b[j]) //如果a[i]==b[j]
            {
                if(f[j]<k+1) //就在0到j-1之间,找一个b[k]小于a[i]的f[k]值最大的解
                    f[j]=k+1;
            }
            if(a[i]>b[j]) //0到j-1中,对于小于a[i]的,保存f值的最优解
            {
                
                if(k<f[j])
                    k=f[j];
            }
        }
    }
    int ans=0;
    for(i=0;i<m;i++)
        ans=max(ans,f[i]);
    return ans;
}

int main()
{
    int t,i,j;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        m = n;
        for(j=0;j<m;j++)
        {
            scanf("%d",&b[j]);
        }
        printf("%d",LCIS());

    return 0;
}

带通配符的字符串匹配

有AB两个串,A串里有? 和 * 表示通配符,?可以指代任意一个字符,*可以指代多个字符(也可以什么都不指代),问这两个串是否匹配

做这个题,一定要反复慎重考虑边界问题

首先,星号可以表示什么都没有,所以B串的递推要从0开始

如果遇到星号,就逆着B串匹配的位置往前找,如果星号之前A串能与B串的某一位置匹配那么他就能匹配,还要注意到0的问题,因为星号之前可能全是星号

如果不是,就看此位置和上个位置是否都匹配,注意这个时候B串的位置必须大于0

这样就可以过了

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
char a[200],b[200];
int dp[200][200];
int main(){

    scanf("%s%s",a,b);
    int lena = strlen(a),lenb = strlen(b);
    int pta = 0,ptb = 0;
    dp[0][0] = 1;
    for(int i = 1;i <= lena;i++){
        for(int j = 0;j <= lenb;j++){
            if(a[i-1] == '*'){
                for(int k = j;k >= 0;k--){
                    if(dp[i-1][k]){
                        dp[i][j] = 1;
                        break;
                    }
                }
            }else if((a[i-1] == b[j-1] || a[i-1] == '?') && (j&&dp[i-1][j-1])){
                 dp[i][j] = 1;
            }
        }
    }
    if(dp[lena][lenb]) cout<<"matched";
    else cout<<"not matched";
    return 0;
}

 

相关文章:

  • 2022-12-23
  • 2021-03-26
  • 2021-12-21
  • 2021-10-11
  • 2021-07-03
  • 2021-06-13
  • 2021-04-26
猜你喜欢
  • 2022-12-23
  • 2021-06-03
  • 2021-12-18
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案