HDU 6170 递推 DP,思考状态的递进

来源:互联网 发布:dota2比赛数据直播 编辑:程序博客网 时间:2024/06/03 20:15

递推 DP,思考状态的递进

题意:

​ 给出一个原串和一个需要匹配的串,当然匹配串有两种操作。

  • ‘.’ 可以变成任何字母 可以使得前一个字母变成任何长度>= 0,例如:
    aaaaaaa

问是否能从匹配串变成原串。

题意:

​ 当前串能不能匹配需要知道之前一个串状态,很明显的dp问题,为什么我当时没有想出来?为什么我要用复杂的dfs去不断超时。

​ 因为匹配串可以增长或者剪短,所以首先需要思考枚举匹配串,然后再思考状态

​ 定义:dp[i][j] 匹配串的长度为i,原串的长度为j是否能匹配,值为1代表可以匹配成功,0代表不可以匹配成功。

​ 假设s1为原串,s2为匹配串。

  • s1[j]==s2[i]||s2[i]==. 的时候只能看前一个状态是否可以匹配dp[i1][j1]
  • s2[i]== ,思考的 功能:当可以删除i-1这个字母的时候:dp[i2][j]=true ,当不增也不减的时候 :dp[i1][j]==true ,当需要增加的时候:(dp[i1][j1]==truedp[i][j1])s1[j]==s1[j1]

然后两重循环可以解决。需要一个特判:当s2[2]== dp[2][0]=true

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 2505;char s1[maxn],s2[maxn];int dp[maxn][maxn];int main(){    //freopen("in.txt","r",stdin);    int t;    scanf("%d",&t);    while(t--) {        memset(dp,0,sizeof(dp));        scanf("%s%s",s1+1,s2+1);        int len1 = strlen(s1+1);        int len2 = strlen(s2+1);        dp[0][0] = 1;        for(int i = 1;i <= len2; i++) {            if(i == 2 && s2[i] == '*') dp[i][0] = true;            for(int j = 1;j <= len1; j++) {                if(s2[i] == s1[j] || s2[i] == '.') dp[i][j] = dp[i-1][j-1];                if(s2[i] == '*') {                    if( (dp[i-1][j-1] || dp[i][j-1]) && s1[j] == s1[j-1]) {                        dp[i][j] = true;                    }                    else if(dp[i-1][j] || dp[i-2][j]) {                        dp[i][j] = true;                    }                }            }        }        if(dp[len2][len1])            printf("yes\n");        else            printf("no\n");    }    return 0;}
原创粉丝点击