题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6170
题目描述: 两个字符串问是否匹配, '.'可以匹配任意字符, '*'可以使前一个数的出现次数成上一个自然数(0, 1, 2, 3........)
解题思路: DP, dp(i, j)表示A串匹配到j位, B串匹配到i位两个串是否匹配, 转移方程再代码里有, 参考Jaihk662的博客, 注释在代码中
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define mem0(a) memset(a,0,sizeof(a)) #define meminf(a) memset(a,-0x3f,sizeof(a)) #define fi(n) for(i=0;i<n;i++) #define fj(m) for(j=0;j<m;j++) #define sca(x) scanf("%d",&x) #define ssca(x) scanf("%s",x) #define scalld(x) scanf("%I64d",&x) #define print(x) printf("%d ", x) #define printlld(x) printf("%I64d ",x) #define de printf("======= ") #define yes printf("YES ") #define no printf("NO ") typedef long long ll; using namespace std; const int maxn = 2600; char a[maxn]; char b[maxn]; int dp[maxn][maxn]; // dp[i][j] 表示 b串匹配到了第i个,a串匹配到了第j个时, 是否匹配 int main() { int t; sca( t ); while( t-- ) { mem0(dp); ssca(a+1); ssca(b+1); int la = (int)strlen(a+1); int lb = (int)strlen(b+1); dp[0][0] = 1; if( b[2] == '*' ) dp[2][0] = 1; //初始化 for( int i = 1; i <= lb; i++ ) { for( int j = 1; j <= la; j++ ) { if( b[i] == '.' ) { // 如果当前位是'.'或者相等就直接转移 dp[i][j] = max(dp[i][j], dp[i-1][j-1] ); } else if( b[i] != '*' ){ if( b[i] == a[j] ) { dp[i][j] = max(dp[i][j], dp[i-1][j-1] ); } } else { //当前是'*' dp[i][j] = max( dp[i-1][j], dp[i-2][j] ); if( (dp[i-1][j-1] || dp[i][j-1]) && a[j] == a[j-1] ) { /*如果前一位匹配上一位已经匹配或者本位已经匹配 且a串的前后相邻两个字符相等, 主要解决aaaaaaaaaaaaa 和 a* 的这种情况*/ dp[i][j] = max( dp[i][j], max(dp[i-1][j-1], dp[i][j-1]) ); } } } } if( dp[lb][la] ) { printf( "yes " ); } else { printf( "no " ); } } return 0; }
思考: 一开始想枚举直接判断了, 结果很快就WA了,越到后面越复杂, 心不细就不要枚举......我没想到这道题也能用DP做, 真的是长见识了, 看来对于DP still have a long way to go 啊...... 感觉暑假快结束了, 自己到底有没有提高呢