HDU

来源:互联网 发布:异构数据库交互 编辑:程序博客网 时间:2024/06/05 18:33

原题链接

      HDU 6170

分析

      输入两个字符串st。定义状态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;}
原创粉丝点击