九度OJ 1006

本文解析了一道关于ZOJ字符串匹配的编程题,详细介绍了题目的规则与解决思路,并给出了具体的代码实现。同时,文章还分享了一种简洁高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
对给定的字符串(只包含'z','o','j'三种字符),判断他是否能AC。

是否AC的规则如下:
1. zoj能AC;
2. 若字符串形式为xzojx,则也能AC,其中x可以是N个'o' 或者为空;
3. 若azbjc 能AC,则azbojac也能AC,其中a,b,c为N个'o'或者为空;
输入:
输入包含多组测试用例,每行有一个只包含'z','o','j'三种字符的字符串,字符串长度小于等于1000。
输出:
对于给定的字符串,如果能AC则请输出字符串“Accepted”,否则请输出“Wrong Answer”。
样例输入:
zoj
ozojo
ozoojoo
oozoojoooo
zooj
ozojo
oooozojo
zojoooo
样例输出:
Accepted
Accepted
Accepted
Accepted
Accepted
Accepted
Wrong Answer
Wrong Answer

额,这道题快Wrong到吐血,一直不知道哪里考虑的不周全,从0分到20分,到40分,到60分。。。最后终于A了。
题目大意:对于满足三条规则的字符串,输出Accepted,否则输出Wrong Answer
第一条很好判断,直接判断是否字符串相等;第二条只要判断zoj前后的'o'是否相等,注意这里只能是o,如果出现其他字符,立马排除;
第三条规则最难处理,因为它是以递归的形式给出的,规则是若X成立,则Y一定成立。我的思路是要判断Y是否成立,先转换成X的形式,判断X是否成立,成立最好,不成立再递归判断,直到出现不能转换,或者转换后可以立马判断是否符合的情况。
答题思路是这样,但实际做的过程中,很多情况刚开始没考虑到。
比如z,o,zz,jj,zojzoj,jjzojj都是不符合条件的情况,很容易遗漏。

#include <iostream>
using namespace std;

int judge1(string str){
    if(str == "xx")
        return 0;
    if(str == "zoj")
        return 1;
    int x = 0;
    for(int i=0;i<str.length();i++){
        if(str[i]=='z'&&str[i+1]=='o'&&str[i+2]=='j'){
            x = i;
            break;
        }
    }
    if(x == 0)
        return 0;    //表示不存在连续的zoj序列
    int count1=0,count2=0;
    for(int i=0;i<x;i++){
        if(str[i] != 'o')
            return 0;
        else
            count1++;
    }
    for(int i=x+3;i<str.length();i++){
        if(str[i] != 'o')
            return 0;
        else
            count2++;
    }
    if(count1 == count2)
        return 1;
    return 0;
}

string transition(string str){
    int num_a_o = 0;
    int num_b_o = 0;
    int num_ac_o = 0;
    int x1=-1,x2=-1;
    for(int i=0;i<str.length();i++){
        if(str[i] == 'z'){
            x1 = i;
            break;
        }
    }
    if(x1 == -1)
        return "xx";   //表示序列中没有z出现的一项
    for(int i=0;i<str.length();i++){
        if(str[i] == 'o'&&str[i+1] == 'j'){
            x2 = i;
            break;
        }
    }
    if(x2 == -1)
        return "xx";  //表示序列中没有oj连续的一项
    for(int i=0;i<x1;i++){
        if(str[i] == 'o')
            num_a_o++;
        else
            return "xx";   //表示转换失败
    }
    for(int i=x1+1;i<x2;i++){
        if(str[i] == 'o')
            num_b_o++;
        else
            return "xx";
    }
    for(int i=x2+2;i<str.length();i++){
        if(str[i] == 'o')
            num_ac_o++;
        else
            return "xx";
    }
    if(num_ac_o<num_a_o)
        return "xx";
    string str1 = "";
    for(int i=0;i<num_a_o;i++)
        str1 += 'o';
    str1 += 'z';
    for(int i=0;i<num_b_o;i++)
        str1 += 'o';
    str1 += 'j';
    for(int i=0;i<num_ac_o-num_a_o;i++)
        str1 += 'o';
    return str1;
}

int main(){
    string str;
    while(cin>>str){
        if(judge1(str))
            cout<<"Accepted"<<endl;
        else{
            if(judge1(transition(str)))
                cout<<"Accepted"<<endl;
            else{
                bool flag = 0;
                while(transition(str)!="xx"){
                    str = transition(str);
                    if(judge1(str)){
                        cout<<"Accepted"<<endl;
                        flag = 1;
                        break;
                    }
                }
                if(flag == 0)
                    cout<<"Wrong Answer"<<endl;
            }
        }
    }
    return 0;
}

当然这只是我比较常规的想法,网上看到大神的思路是这样的,只要判断z前面o的个数*z和j之间o的个数是否等于j后面o的个数。
我后来验证了一下,用数学归纳法证明发现是对的,感觉好简单。。不过这不是一般人能够想到的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值