记忆化搜索(字符串)——Kickstart 2017(Google Code Jam) A Round #B

  • 题目链接: https://codejam.withgoogle.com/codejam/contest/8284486/dashboard#s=p1

  • 题意: 给出2个字符串A和B,判断2个字符串是否相等,字符串中可能含有’*’符号,这个符号可以与0~4个任意字符匹配上。

  • 分析: 我们可以发现一点就是,对于每一个 ‘*’,我们可以选择让它匹配0~4个字符再对接下来的字符进行比对,那么我们可以直接搜索它分别匹配0~4个字符的结果,并用一个二维数组DP[i][j]来记录匹配的结果:表示A串的第i个字符和B串的第j个字符是否匹配成功。在这之前,我们需要将字符串中的每一个 ‘*’ 都用4个0来替换,并且每一个0都能和任意字符匹配。

  • 递推方程:

DP[0][0] = 1 //0位置的时候自然匹配成功
if(DP[i][j])
{
    DP[i+1][j] |= A[i+1]=='0'; //跳过A串一个0
    DP[i][j+1] |= B[j+1]=='0'; //跳过B串一个0
    DP[i+1][j+1] |= A[i+1]=='0'||B[j+1]=='0'||A[i+1]==B[j+1];//匹配A串一个0||匹配B串一个0||匹配A,B串一个字符
}
  • Correct代码:
/*************************************************************************
    > File Name: test.cpp
    > Author: Akira 
    > Mail: [email protected] 
 ************************************************************************/

#include
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;

#define MaxN 10001
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
const int mod = 1E9+7;
const double eps = 1e-6;
#define bug cout<<88888888<" = " << x;
int T;
char A[MaxN],B[MaxN],str[MaxN];
int N,M;
void check(char *s,int flag)
{
    int i,j;
    for(i=0,j=0;iif(s[i] == '*')
        {
            if(flag) 
            {
                A[++j] = '0';
                A[++j] = '0';
                A[++j] = '0';
                A[++j] = '0';
            }
            else
            {
                B[++j] = '0';
                B[++j] = '0';
                B[++j] = '0';
                B[++j] = '0';
            }
        }
        else
        {
            if(flag) A[++j] = s[i];
            else B[++j] = s[i];
        }
    }
    if(flag) N = j;
    else M = j;
}
int DP[MaxN][MaxN];
int main()
{
    //std::ios::sync_with_stdio(false);
    freopen("B-large-practice.in","r",stdin);
    freopen("B.out","w",stdout);
    /********************************************/
    scanf("%d", &T);
    for(int t=1;t<=T;t++)
    {
        scanf("%s",str);
        check(str,1);
        scanf("%s",str);
        check(str,0);
        CLR(DP);
        DP[0][0] = 1;
        for(int i=0;i<=N;i++)
        {
            for(int j=0;j<=M;j++)
            {
                if(DP[i][j])
                {
                    DP[i+1][j] |= A[i+1]=='0';
                    DP[i][j+1] |= B[j+1]=='0';
                    DP[i+1][j+1] |= A[i+1]=='0'|| B[j+1]=='0' || A[i+1]==B[j+1];
                }
            }
        }
        if(DP[N][M]) printf("Case #%d: TRUE\n", t);
        else printf("Case #%d: FALSE\n", t);
    }
    /********************************************/
    fclose(stdin);
    fclose(stdout);
    return 0;
}

你可能感兴趣的:(ACM算法(题解):,动态规划,字符串)