zoukankan      html  css  js  c++  java
  • HDU 6170----Two strings(DP)

    题目链接

    Problem Description
    Giving two strings and you should judge if they are matched.
    The first string contains lowercase letters and uppercase letters.
    The second string contains lowercase letters, uppercase letters, and special symbols: “.” and “*”.
    . can match any letter, and * means the front character can appear any times. For example, “a.b” can match “acb” or “abb”, “a*” can match “a”, “aa” and even empty string. ( “*” will not appear in the front of the string, and there will not be two consecutive “*”.
     
    Input
    The first line contains an integer T implying the number of test cases. (T≤15)
    For each test case, there are two lines implying the two strings (The length of the two strings is less than 2500).
     
    Output
    For each test case, print “yes” if the two strings are matched, otherwise print “no”.
     
    Sample Input
    3
    aa
    a*
    abb
    a.*
    abb
    aab
     
    Sample Output
    yes
    yes
    no
     
     
    题意:给了两个字符串,判断是否匹配。第一个串只包含小写和大写字符,第二个串包含小写、大写字符,还包括‘ . ’和' * ',' . ' 可以匹配任意一个字符,' * ' 表示' * '之前的字符可以重复多次,比如a*可以匹配a、aa、aa……以及空串(注:第二个串不会以' * '开始,也不会有两个连续的' * ')。
     
    思路:考虑DP,每次根据1~i的b串能使a串到达哪些位置,进而推出1~i+1的b串能使a串到达哪些位置。
     
    代码如下:
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=2505;
    char a[N],b[N];
    int len1,len2;
    int dp[N][N];
    
    int main()
    {
        int T; cin>>T;
        while(T--){
           scanf("%s%s",a+1,b+1);
           len1=strlen(a+1);
           len2=strlen(b+1);
           memset(dp,0,sizeof(dp));
           dp[0][0]=1;
           for(int i=1;i<=len2;i++)
           {
               if(b[i]=='.')
               {
                  for(int j=0;j<=len1;j++)
                  {
                      if(dp[i-1][j]) dp[i][j+1]=1;
                  }
               }
               else if(b[i]=='*')
               {
                  for(int j=0;j<=len1;j++)
                  {
                      if(dp[i-1][j])
                      {
                         dp[i][j]=1;
                         dp[i][j-1]=1;
                         while(a[j+1]==a[j]) dp[i][j+1]=1,j++;
                      }
                  }
               }
               else
               {
                  for(int j=0;j<=len1;j++)
                  {
                      if(!dp[i-1][j]) continue;
                      if(a[j+1]==b[i]) dp[i][j+1]=1;
                      else if(b[i+1]=='*') dp[i+1][j]=1;
                  }
               }
           }
           if(dp[len2][len1]) puts("yes");
           else puts("no");
        }
        return 0;
    }
    /*
    .*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*
    */

    比赛中我用的深搜模拟的,会超时,但是如果答案是"yes"的话,会很快的计算出,不会超时;如果是” no "的话,会搜索所有的情况,会超时,这个时候我们可以用一个变量记录一下递归次数,当大于一定次数时默认为“no”的情况,退出搜索。(当然这种做法不是正解,脑洞大开,如果有厉害的数据肯定过不了~)

    代码如下:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=2505;
    char a[N],b[N];
    int len1,len2;
    int h[N];
    int c;
    int dfs(int i,int j)
    {
        c++;
        if(c>1000000) return 0;///默认为"no"的情况;
        if(i<len1 && j>=len2) return 0;
        if(i>=len1){
            if(j>=len2) return 1;
            if(j==len2-1 && b[j]=='*') return 1;
            if(j==len2-1 && b[j]!='*') return 0;
            if(j<len2-1){
                if(b[j]=='*' && h[j+1]) return 1;
                else if(b[j]!='*' && h[j]) return 1;
                else return 0;
            }
        }
        if(b[j]=='.') { b[j]=a[i]; int f=dfs(i+1,j+1); b[j]='.'; return f; }
        if(b[j]=='*') {
            if(a[i]==b[j-1]){
                if(dfs(i+1,j)) return 1;
                if(dfs(i,j+1)) return 1;
                if(dfs(i-1,j+1)) return 1;
             }
            else {
                if(dfs(i-1,j+1)) return 1;
                if(dfs(i,j+1)) return 1;
            }
        }
        if(a[i]==b[j]) return dfs(i+1,j+1);
        else if(b[j+1]=='*') return dfs(i,j+2);
        else return 0;
    }
    
    int main()
    {
        int T; cin>>T;
        while(T--){
           scanf("%s%s",a,b);
           c=0;
           len1=strlen(a);
           len2=strlen(b);
           int flag=1;
           for(int i=len2-1;i>=0;i--)
           {
               if(!flag) h[i]=0;
               else if(b[i]=='*'){
                  h[i]=1; h[i-1]=1; i--;
               }
               else{
                  h[i]=0;
                  flag=0;
               }
           }
           int ans=dfs(0,0);
           if(ans) puts("yes");
           else puts("no");
        }
        return 0;
    }
    /*
    .*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*
    */
  • 相关阅读:
    Vue 子组件接收父组件的值
    Vue 子组件调用父组件的方法
    dedecms大量删除文章后,列表页显示错误修复办法
    怎么才能快速的删除指定栏目、指定日期、指定id之间的织梦文章内容?
    怎么才能快速的彻底删除织梦文章内容?
    织梦删除专题,删除文章时出现错误inc_batchup.php on line 17 如何解决?
    windows环境下更改Mysql数据库存储位置的具体步骤
    JsonP原理
    建一个别人打不开的文件夹
    Dos环境变量修改
  • 原文地址:https://www.cnblogs.com/chen9510/p/7421662.html
Copyright © 2011-2022 走看看