USTCOJ 1324 Zipper 判断连续出现字符

以下两份代码采用了hzq(这里)的解题思路。即在输入的a、b、c三个串中,如果c串有连续出现的字符,那么这些字符必定也在a或/和b中连续存在。基于这一思路,能够快速的处理tttttt tttttt tttttttttttt这样的输入。

代码一:递归+连续字符判断。

其中45~55的代码写得很漂亮。

/*
* 作者:hzq
* 修改前代码id:73251
* 修改者:lance
*/
#include <stdio.h>
#include <string.h>

int zipper(char *ch1, char *ch2, char *ch3)
{
    int k, m, n;
    
    if (!*ch3)
        return 1;
    
    k = 1;
    while(*ch3 == *(ch3 + k))  k++;
    if (k > 2)
    {
        m = 0;
        while(*(ch2 + m) == *ch3) m++;
        n = 0;
        while(*(ch1 + n) == *ch3) n++;

        //最多只能从ch1或ch2中提取k个相同字符到ch3中
        m = k < m ? k : m;
        n = k < n ? k : n;
        
        if (*(ch2 + m) == *(ch3 + k))
        {
            ch1 += k - m;
            ch2 += m -1;
            ch3 += k -1;
        }
        else if (*(ch1 + n) == *(ch3 + k))
        {
            ch1 += n -1;
            ch2 += k - n;
            ch3 += k -1;
        }
        else if (m+n <= k+1)
            return 0;
    }
    
    if ((ch1[0] == ch3[0]) || (ch2[0] == ch3[0]))
    {
        int i = 0;
        if (ch1[0] == ch3[0])
            i = zipper(ch1+1, ch2, ch3+1);
        if (!i && ch2[0] == ch3[0])
            i = zipper(ch1, ch2+1, ch3+1);
        return i;
    }
    else
        return 0;
}


int main()
{
    //freopen("1324.in", "r", stdin);
    //freopen("1324.out", "w", stdout);
    char str1[460], str2[460];
    char str3[910];
    int d, n;
    scanf("%d\n", &n);
    for (d = 1; d <= n; d++)
    {
        scanf("%s%s%s", str1, str2, str3);
        if ((strlen(str1) + strlen(str2)) != strlen(str3))
        {
            printf("Data set %d: no\n", d);
            continue;
        }
        
        if (zipper(str1, str2, str3))
            printf("Data set %d: yes\n", d);
        else
            printf("Data set %d: no\n", d);
    }
    return 0;
}


代码二:递归+循环+连续字符判断。

通过循环减少递归层次,避免数据过大时堆栈溢出。

/*
*作者:lance
*/
#include <stdio.h>
#include <string.h>

int zipper(char *a, char *b, char *c)
{
    while (1)
    {
        int k, m, n;        
        if (*c == 0)
            return 1;       
        k = 1;
        while (*c == *(c + k)) k++;
        
        if (k == 1)
        {
            if (*a == *b)
            {
                if (*c == *a)
                    return zipper(a+1, b, c+1)  || zipper(a, b+1, c+1);
                else
                    return 0;
            }
            
            if (*c == *a)
            {
                a++, c++;
                continue;
            }
            else if (*c == *b)
            {
                b++, c++;
                continue;
            }
            else
                return 0;
        }
        
        //k!= 1的情况下,执行以下动作;
        m = 0;
        while (a[m] == *c) m++;     
        n = 0;
        while (b[n] == *c) n++;
        
		//m+n 与 k的三种关系
        if (m+n < k)
            return 0;       
        if (m+n == k)
        {
            a += m, b += n, c += k;
            continue;
        }
        
        //k != 1 且 m+n > k的情况下,执行以下动作;
        m = k < m ? k : m;
        n = k < n ? k : n;      
        return zipper(a+m, b+k-m, c+k) || zipper(a+k-n, b+n, c+k);
    }
}

int main()
{
	//freopen("1324.in", "r", stdin);
	//freopen("1324.out", "w", stdout);
    char str1[460], str2[460];
    char str3[910];
    int d, n;
    scanf("%d\n", &n);
    for (d = 1; d <= n; d++)
    {
        scanf("%s%s%s", str1, str2, str3);
        if ((strlen(str1) + strlen(str2)) != strlen(str3))
        {
            printf("Data set %d: no\n", d);
            continue;
        }

        if (zipper(str1, str2, str3))
            printf("Data set %d: yes\n", d);
        else
            printf("Data set %d: no\n", d);
    }
    return 0;
}


你可能感兴趣的:(USTCOJ 1324 Zipper 判断连续出现字符)