USTCOJ 1324 Zipper 存储计算结果

在USTCOJ的1324这道题中,当遇到tttttt tttttt tttttttttttt这样的输入实例时,如下伪代码片段效率非常低。因为有很多的重复计算在里面。可通过存储match函数调用结果减少重复计算。

int match(char *a, char *b, char *c)
{
	if *c = 0
		return 1
	if *a = *b = *c
	    return match(a+1, b, c+1) || match(a, b+1, c+1)
	if *a = *c
		return match(a+1, b, c+1)
	if *b = *c
		return match(a, b+1, c+1)
	return 0
}

其中代码一是用数组来存储结果,代码二用stl里面的set存储参数对(pair)。代码中while循环的目的是为了减少递归层次,仅当不能判断应该从哪一个子串(a或/和b)中取字符到主串(c)时,才跳出循环开始递归操作。


代码一:

#include <cstdio>
#include <cstring>
#include <set>
#include <utility>
#define N 500
using namespace std;

char flag[N][N];
char stra[N], strb[N], strc[2*N];

int match(char *a, char *b, char *c)
{
    while (*a || *b)
    {
        if(*c != *a && *c != *b)
            return 0;
        
        if(*a == *b)
            break;
        else
        {            
            if (*a == *c)
                a++, c++;
            else
                b++, c++;
        }
    }
    //此时*a == *c,所以两重递归
    if (*a)
    {
        if (flag[a+1-stra][b-strb] == 0)
        {
            if (match(a+1, b, c+1))
                return 1;
            else
                flag[a+1-stra][b-strb] = 1;
        }
        if (flag[a-stra][b+1-strb] == 0)
        {
            if (match(a, b+1, c+1))
                return 1;
            else
                flag[a-stra][b+1-strb] = 1;
        }
        return 0;
    }
    //若*a == '\0',表示a、b字符串中的字符均已在c中匹配,故返回匹配成功
    else
        return 1;
}

int main()
{
    freopen("1324.in", "r", stdin);
    freopen("1324.out", "w", stdout);
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        memset(&flag[0][0], 0, N*N*sizeof(flag[0][0]));
        scanf("%s%s%s", stra, strb, strc);
        if (match(stra, strb, strc))
            printf("Data set %d: yes\n", i);
        else
            printf("Data set %d: no\n", i);
    }
    return 0;
}

代码二:

#include <cstdio>
#include <cstring>
#include <set>
#include <utility>
using namespace std;

typedef pair<char *, char *> MyType;
set<MyType> dpresult;

int match(char *a, char *b, char *c)
{
    while (*a || *b)
    {
        if(*c != *a && *c != *b)
            return 0;
        
        if(*a == *b)
            break;
        else
        {            
            if (*a == *c)
                a++, c++;
            else
                b++, c++;
        }
    }
    //此时*a == *c,所以两重递归
    if (*a)
    {
        MyType p(a+1, c+1);
        if (dpresult.find(p) == dpresult.end())
        {
            if (match(a+1, b, c+1))
                return 1;
            else
                dpresult.insert(p);
        }
        p.first = b+1;
        if (dpresult.find(p) == dpresult.end())
        {
            if (match(a, b+1, c+1))
                return 1;
            else
                dpresult.insert(p);
        }
        return 0;
    }
    //若*a == '\0',表示a、b字符串中的字符均已在c中匹配,故返回匹配成功
    else
        return 1;
}

int main()
{
    freopen("1324.in", "r", stdin);
    freopen("1324.out", "w", stdout);
    char a[500], b[500], c[1000];
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        dpresult.clear();
        scanf("%s%s%s", a, b, c);
        if (match(a, b, c))
            printf("Data set %d: yes\n", i);
        else
            printf("Data set %d: no\n", i);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值