CSU - 2056 a simple game (KMP)(reverse函数)

题目链接

题目描述:

这一天,小A和小B在玩一个游戏,他俩每人都有一个整数,然后两人轮流对他们的整数进行操作,每次在下列两个操作任选一个:
(1)对整数进行翻转,如1234翻转成4321 ,1200翻转成21 
(2)将整数除以10,如1234/10=123,1/10=0 
当操作过程中出现a==b时,则小A就赢了,而操作一直进行下去或不能使a==b则算小B赢。 
现在小A求助于你,想让你帮他在知道两人的整数时小A能不能赢,假设每次都是小A先手,并且两人都是采取最优策略 

Input

首先输入T(T <= 100),表示有T组数据,然后接下来有T行,每行有两个整数a,b(0 <= a,b < 10100000)

Output

有T行,当小A赢了则输出"Yes",否则输出"No"

Sample Input

4
1234 123
123 321
1234 12345
123 123

Sample Output

Yes
Yes
No
Yes

题目思路:

      其实如果这道题不是放在KMP专题里面,我应该是完全想不到用KMP的(嘤)。

       既然他们都采取的时最优策略,我们就可以这样考虑:B要怎么做才能不让A胜利。由于A采取的也是最优策略,那么可以知道,而且可以翻转和切掉最后的数字,注意:翻转+切掉最后的数字也就是告诉我们,A可以得到所有它的子串。那么,如果B或者B翻转之后是A的子串,那么A就一定可以通过翻转和切掉数字的操作是自己的数字等于B!

       这里不用考虑B的子串是因为:B采取的也是最优策略,如果它的子串是A的子串,那么A肯定可以得到,B是绝对不会这样做的。

需要注意的一点是:翻转之后的前导0要去掉,比如1200翻转后是21,处理一下就好。

另:STL中的翻转函数reverse

题目代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define maxn 1000005

using namespace std;
char a[maxn],b[maxn];
int nxt[maxn];

void build(char s[],int n)
{
     int k=0;nxt[0]=0;
     for(int i=1;i<n;i++)
     {
          while(k&&s[i]!=s[k])
               k=nxt[k-1];
          if(s[i]==s[k])
               k++;
          nxt[i]=k;
     }
}
bool kmp(char w[],char s[],int lw,int ls)
{
     build(s,ls);
     int j=0;
     for(int i=0;i<lw;i++)
     {
          while(j&&w[i]!=s[j])
               j=nxt[j-1];
          if(w[i]==s[j])
               j++;
          if(j==ls)
               return true;
     }
     return false;
}
int main(void)
{
     int t;
     int k,flag;
     scanf("%d",&t);
     while(t--)
     {
          memset(nxt,0,sizeof(nxt));
          scanf("%s%s",a,b);
          int la=strlen(a);
          int lb=strlen(b);
          for(int i=la-1;i>=0;--i)//去掉A后面的0
          {
               if(a[i]!='0')
                    break;
               a[i]='\0';
          }
          la=strlen(a);
          for(int i=lb-1;i>=0;--i)//去掉B后面的0,为了方便后面翻转
          {
               if(b[i]!='0')
                    break;
               b[i]='\0';
          }
          lb=strlen(b);
          if(lb>la)//如果B的长度大于A显然不会
          {
               printf("No\n");
               continue;
          }
          if(lb==0||kmp(a,b,la,lb))//看B是不是A的子串
          {
               printf("Yes\n");
               continue;
          }
          reverse(b,b+lb);
          //puts(b);
          memset(nxt,0,sizeof(nxt));
          if(kmp(a,b,la,lb))//看B的翻转是不是A的子串
               printf("Yes\n");
          else
               printf("No\n");
     }
     return 0;
}

呼呼

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81587873