您的位置:首页 > 其它

HDU - 6170 Two strings dp

2017-08-23 13:37 351 查看

原题链接

HDU 6170

分析

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

如果s[i]==t[j] || t[j] ==‘.’,则dp[i][j]=dp[i−1][j−1]

如果t[j] ==‘*’,分为下面两种情况。

(1) t[j−1] != s[i] && t[j−1] !=‘*’,此时‘*’不能匹配任何字符。所以

dp[i][j]=dp[i][j−2]

(2) 除了(1)之外的情况,‘*’可以匹配0到多个s[i]字符。 假设s[k...i]是一段连续且相等的字符,则dp[i][j]=dp[k−1][j−2] || dp[k][j−2] || dp[k+1][j−2] || … || dp[i][j]

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

代码

#include <bits/stdc++.h>

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

;
bool sum
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp