HDU - 6170 Two strings dp

原题链接

      HDU 6170

分析

      输入两个字符串 s t 。定义状态 dp[i][j] 表示 s[1...i] t[1...j] 是否可以匹配成功。

  1. 如果 s[i]==t[j] || t[j] ==‘.’,则 dp[i][j]=dp[i1][j1]
  2. 如果 t[j] ==‘*’,分为下面两种情况。
    (1) t[j1] != s[i] && t[j1] !=‘*’,此时‘*’不能匹配任何字符。所以
    dp[i][j]=dp[i][j2]
    (2) 除了(1)之外的情况,‘*’可以匹配0到多个 s[i] 字符。 假设 s[k...i] 是一段连续且相等的字符,则 dp[i][j]=dp[k1][j2] || dp[k][j2] || dp[k+1][j2] || … || dp[i][j]

      但是如果这样写的话时间复杂度最坏可以达到 O(N3) 。主要是因为红色部分状态转移代价太大。注意到红色部分其实就是个后缀的关系,只需要维护一个 sum 数组, sum[i][j]=dp[k1][j] || dp[k][j] || dp[k+1][j] || … || dp[i][j] ,其中 s[k...i] 是一段连续且相等的字符。这样一来红色部分就可以写成 dp[i][j]=sum[i1][j2] || dp[i][j2] 了。更新 sum[i][j] 的代价是 O(1) 的,因为 sum[i][j]=sum[i1][j] || dp[i][j] 。总的复杂度是 O(N2)

代码

#include <bits/stdc++.h>

using namespace std;
const int N = 2505;
char s[N], t[N];
int lens, lent;
bool dp[N][N];
bool sum[N];

int main()
{
    //freopen("test.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%s%s", s + 1, t + 1);
        lens = strlen(s + 1);
        lent = strlen(t + 1);
        memset(dp, false, sizeof(dp));
        memset(sum, false, sizeof(sum));
        for (int i = 0; i <= lens; i++)
        {
            for (int j = 0; j <= lent; j++)
            {
                if (!i && !j)
                {
                    dp[0][0] = true;
                    continue;
                }
                if (t[j] == s[i] || t[j] == '.')
                    dp[i][j] = dp[i - 1][j - 1];
                else if (t[j] == '*')
                {
                    if (t[j - 1] != s[i] && t[j - 1] != '.')
                        dp[i][j] = dp[i][j - 2];
                    else if (s[i] == s[i - 1])
                        dp[i][j] = sum[j - 2] || dp[i][j - 2];
                    else
                        dp[i][j] = dp[i][j - 2] || dp[i - 1][j - 2];
                }
            }
            for (int j = 0; j <= lent; j++)
                if (s[i] == s[i - 1])
                    sum[j] = sum[j] || dp[i][j];
                else
                    sum[j] = dp[i][j] || dp[i - 1][j];
        }
        if (dp[lens][lent])
            printf("yes\n");
        else
            printf("no\n");
    }
    return 0;
}
发布了173 篇原创文章 · 获赞 28 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/ECNU_LZJ/article/details/77504925