• HDU 6170 Two strings( DP+字符串匹配)


    http://acm.hdu.edu.cn/showproblem.php?pid=6170

    题目大意:

    给出两个字符串s1和s2(长度小于等于2500)。

    s1是一个正常的包含大小写字母的字符串,s2是一个类似正则表达式的字符串,除了大小写字母,还有 " . " 和 " * " 两种符号。

    " . " 表示可以匹配任意一个字母。

    " * ”表示前一个字符可以重复出现任意次(包括零)。

    解题思路:

    一道标准的dp O(n^2)。

    用dp[i][j]来表示s2的前i个字符和s1的前j个字符能否匹配。

    对于s2的每一个字符都跑一遍s1的全部字符dp,分别会遇到以下几种情况:

    1.s2的该字符是 " * ",而且恰好是第二个字符,那么建立dp起点,也就是dp[i][0]=1;

    2.s2的该字符是 " . ",那么说明s2的第j个字符匹配s1的第i个字符成立,dp[i][j]=dp[i-1][j-1];

    3.s2的该字符是 " * ",而且不是第二个字符,那么首先考虑到的情况是 * 前一个字符出现0次的情况,所以至少有dp[i][j]=max(dp[i-2][j],dp[i-1][j]);

    这种情况举例可以是 s1: abb   s2: abbc*   dp[i][j]=dp[i-2][j]

    4.在第3个情况的前提,在 * 对应的前一个字符可能出现非零次时,如果 * 之前的字符都能全部匹配好: dp[i][j-1]==1 而且s1的第j个字符重复了: s1[j]==s1[j-1]的情况下,举例: s1: abbcccc   s2: abbc*

    那么很显然只要判断 s2[i-1]==s1[j]成立 或者 s2[i-1]=='.' ,这两个满足任意一个都说明 " * "成功匹配到s1的第j个字符。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<map>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<bitset>
    #include<functional>
    
    using namespace std;
    
    #define LL long long
    const int INF = 0x3f3f3f3f;
    
    int dp[2505][2505];
    char s1[2505],s2[2505];
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s%s",s1+1,s2+1);
            memset(dp,0,sizeof(dp));
            int len1=strlen(s1+1),len2=strlen(s2+1);
            dp[0][0]=1;
            for(int i=1;i<=len2;i++)
            {
                if(s2[i]=='*'&&i==2) dp[i][0]=1;
                for(int j=1;j<=len1;j++)
                {
                    if(s2[i]=='.') dp[i][j]=dp[i-1][j-1];
                    else if(s2[i]!='*')
                    {
                        if(s2[i]==s1[j]) dp[i][j]=dp[i-1][j-1];
                    }
                    else
                    {
                        dp[i][j]=max(dp[i-2][j],dp[i-1][j]);
                        if(dp[i][j-1]&&s1[j]==s1[j-1])
                        {
                            if(s2[i-1]==s1[j] || s2[i-1]=='.') dp[i][j]=1;
                        }
                    }
                }
            }
            if(dp[len2][len1])
                cout<<"yes"<<endl;
            else
                cout<<"no"<<endl;
        }
        return 0;
    }
     
  • 相关阅读:
    hdu 1754
    hdu 1166
    poj 1193
    如何由XSD自动生成XML和实体类
    WinForm(C#)CheckedlistBox绑定数据,并获得选中的值(ValueMember)和显示文本(DisplayMember)
    C#读写共享文件夹
    去除TFS版本控制信息
    SQL 触发器
    C#中操作WMI的类库-实现远程登录共享
    VS 制作安装包小窥
  • 原文地址:https://www.cnblogs.com/YingZhixin/p/7589872.html
Copyright © 2020-2023  润新知