zoukankan      html  css  js  c++  java
  • 动态规划

    带通配符的字符串匹配

    http://noi.openjudge.cn/ch0206/6252/

    #include <bits/stdc++.h>
    using namespace std;
    int main(){
        bool dp[30][30]={0};
        dp[0][0]=1;
        string x,y,t=" "; 
        cin>>x>>y;
        x=t+x,y=t+y;
        for(int i=1;i<x.size();i++){
            if(x[i]=='*')
                dp[i][0]=1;
            else
                break;
        }
        for(int i=1;i<x.size();i++){
            for(int j=1;j<y.size();j++){
                if(x[i]==y[j]||x[i]=='?'){
                    dp[i][j]=dp[i-1][j-1];
                }
                else if(x[i]=='*'){
                    if(dp[i-1][j-1]||dp[i-1][j]||dp[i][j-1])
                        dp[i][j]=true;
                    else
                        dp[i][j]=false;
                }
                else if(x[i]!=y[j]){
                    dp[i][j]=false;
                }
            }
        }
        if(dp[x.size()-1][y.size()-1])
            cout<<"matched";
        else
            cout<<"not matched";
    } 
    View Code

    计算字符串距离

    http://noi.openjudge.cn/ch0206/2988/

    #include <iostream>
    #include <cmath>
    #include <memory.h>
    using namespace std;
    int dp[1010][1010];
    int fmin(int x,int y,int z){
        return min(x,min(y,z));
    }
    int main(){
        int T;
        cin>>T;
        while(T--){
            memset(dp,0,sizeof(dp));
            string x,y;
            cin>>x>>y;
            for(int i=0;i<=x.size();i++){
                dp[i][0]=i;
            }
            for(int i=0;i<=y.size();i++){
                dp[0][i]=i;
            }
            for(int i=0;i<x.size();i++){
                for(int j=0;j<y.size();j++){
                    if(x[i]==y[j]) dp[i+1][j+1]=dp[i][j];
                    else dp[i+1][j+1]=fmin(dp[i][j+1],dp[i+1][j],dp[i][j])+1;
                }
            }
            cout<<dp[x.size()][y.size()]<<endl;
    
        }
    }
    View Code

    切割回文

    http://noi.openjudge.cn/ch0206/8471/

    #include <iostream>
    #include <cmath>
    #include <memory.h>
    using namespace std;
    int dp[1010];
    string x;
    bool f(int l,int r){
        for(int i=l;i<=(l+r)/2;i++){
            if(x[i]!=x[l+r-i])
                return 0;
        }
        return 1;
    }
    int main(){
        int T;
        cin>>T;
        while(T--){
            int ans=1e9;
            memset(dp,0x3f,sizeof(dp));
            cin>>x;
            for(int i=0;i<x.size();i++){
                if(f(0,i)) dp[i]=0;
                else{
                    for(int j=i;j>=0;j--){
                        if(f(j,i))
                            dp[i]=min(dp[i],dp[j-1]+1);
                    }
                }
            }
            cout<<dp[x.size()-1]<<endl;
        }
    }
    View Code

     补充:

    11/19

    程序考试,两道原题计算字符串距离、切割回文,

    切割回文没打出来,非常失落,

    没和一维数组联系起来,满脑子递归,

    上次打出来这个题其实也是先打了递归代码,理解了之后再转dp,

    dp和递归区别,在这里就是数组记录了每一次结果,后续不用计算调用之前计算好了的结果,

    爬楼梯这个例子可以好好理解一下。

    考试还有一个失败地方,看见做过的题净想着回忆上次怎么做的,

    然后回忆不起来,裂开。其实就当成新题做就挺好,相信自己。

    哦,递归方法超时了,贴一下代码,很好理解。

     1 #include <iostream>
     2 #include <cmath>
     3 #include <memory.h>
     4 using namespace std;
     5 string x;
     6 bool f(int l,int r){
     7     for(int i=l;i<=(l+r)/2;i++){
     8         if(x[i]!=x[l+r-i])
     9             return 0;
    10     }
    11     return 1;
    12 }
    13 int hh(int l,int r,int ans){
    14     if(f(l,r))
    15         return ans;
    16     else{
    17         int mn=1e9;
    18         for(int i=r;i>=l+1;i--){
    19             if(f(i,r))
    20                 mn=min(mn,hh(l,i-1,ans+1));
    21         }
    22         ans=mn;
    23     }
    24     return ans;
    25 }
    26 int main(){
    27     int T;
    28     cin>>T;
    29     while(T--){
    30         cin>>x;
    31         cout<<hh(0,x.size()-1,0)<<endl;
    32     }
    33 }
    View Code

    打完力扣最长回文子串后,我觉得切割回文我打了一个假的dp,二维矩阵记录是否是回文状态都没有,我再想想。

    明白了,关于判断是否是回文,应该用状态矩阵记录,不然的话,要再写一个for循环判断。。。。我失败了(noi的数据太水了!!!)

    力扣最长回文子串就超时了一上午。。。。

    应该是先两个for得出所有回文子串情况保存在二维数组里,然后f函数那里改成查询二维矩阵相应数值是否为1,这样f这里O(n)时间变成O(1)时间

    奇怪,可能noi数据有问题,之前14s现在21s,时间上确实优化了一个for循环,上代码。

     1 #include <iostream>
     2 #include <cmath>
     3 #include <memory.h>
     4 using namespace std;
     5 int dp[1010];
     6 bool f[1010][1010]; 
     7 string s;
     8 void ff(int n){
     9     for(int i=0;i<n;i++){//长度为1和2的直接初始化 
    10         f[i][i]=1;
    11         if(s[i]==s[i+1])
    12             f[i][i+1]=1;
    13     }
    14     for(int len=3;len<=n;len++){
    15         
    16         for(int i=0;i+len-1<n;i++){
    17             int j=i+len-1;//右边界 
    18             if(s[i]==s[j]&&f[i+1][j-1]){
    19                 f[i][j]=1;
    20             }else{
    21                 f[i][j]=0;
    22             }
    23         }
    24     }
    25 }
    26 int main(){
    27     int T;
    28     cin>>T;
    29     while(T--){
    30         int ans=1e9;
    31         memset(dp,0x3f,sizeof(dp));
    32         cin>>s;
    33         ff(s.size());
    34         for(int i=0;i<s.size();i++){
    35             if(f[0][i]) dp[i]=0;
    36             else{
    37                 for(int j=i;j>=0;j--){
    38                     if(f[j][i])
    39                         dp[i]=min(dp[i],dp[j-1]+1);
    40                 }
    41             }
    42         }
    43         cout<<dp[s.size()-1]<<endl;
    44     }
    45 }
    View Code
  • 相关阅读:
    2019牛客暑期多校训练营(第三场)B题、H题
    2019牛客暑期多校训练营(第四场)k题、j题
    Manacher算法 & Palindrome
    HDU 3336——Count the string
    判断一个点是否在三角形内
    P1052 过河
    P1353 [USACO08JAN]跑步Running
    hdu 1686 Oulipo
    Cyclic Nacklace HDU
    高精地图技术分析
  • 原文地址:https://www.cnblogs.com/hcl6/p/13933881.html
Copyright © 2011-2022 走看看