1. 程式人生 > >6170 Two strings (多校,DP,字串匹配)

6170 Two strings (多校,DP,字串匹配)

題目描述:

題意給你兩串字串,其中'.'可以替換成任意字元,'*'表示前面一個字元可以出現任意次。

用dp來處理,用dp[i][j]來表a[i],b[j]是否匹配,這題有一個及其神奇的操作就是a*可以處理成空串,*居然可以表示出現0次,真的是無比佩服出題人的腦洞,剩下就是狀態轉移,其實都很簡單,只要細心就行,如果b[j]==a[i]或者b[j]=='.'那麼該點肯定可以匹配dp[i][j]=dp[i-1][j-1],如果b[j]=='*'那麼討論這個*的情況,第一處理成空串dp[i][j]=dp[i-2][j],第二不管這個*號,dp[i][j]=dp[i-1][j],然後考慮這個*號如果a[i]==a[i-1]的話,dp[i][j]=dp[i-1][j]||dp[i-1][j-1]。

AC程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<stack>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXM=2505;

bool dp[MAXM][MAXM];
char s1[MAXM],s2[MAXM];


int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s1+1);
        scanf("%s",s2+1);
        memset(dp,false,sizeof(dp));
        dp[0][0]=true;
        if (s2[2]=='*')
            dp[0][2]=true;
        int lena=strlen(s1+1);
        int lenb=strlen(s2+1);
        for (int i=1;i<=lena;i++)
        {
            for (int j=1;j<=lenb;j++)
            {
                if (s1[i]==s2[j])
                    dp[i][j]=dp[i-1][j-1];
                if (s2[j]=='.')
                    dp[i][j]=dp[i-1][j-1];
                if (s2[j]=='*')
                {
                    dp[i][j]=dp[i][j-2]|dp[i][j-1];
                    if (s1[i]==s1[i-1])
                        dp[i][j]=dp[i-1][j]|dp[i-1][j-1];
                }
            }
        }
        if (dp[lena][lenb]) printf("yes\n");
        else printf("no\n");
    }
    return 0;
}