题意
Alice和Bob玩游戏, 他们各自给出两个数字A, B ( 0<=A,B<=10^100000 )
他们可以对这两个数字进行两种操作: 除10 或 反转数字
例如X=123456 , 除10变为12345(而不是 12345.6). 特别注意 0/0=0 (一个坑, 如果Bob给数字是0, 则Alice一定可以一直除10达到0, 也就是说B = 0, Alice一定赢 ).
Alice先手, 问谁会赢
思路
对数字的两种操作实际上就是删A这个字符串的两端, 如果串A中能查找到B或者B的反转串, 那么Alice一定赢, 反之Bob一定赢
这个题对应的是严格的 KMP 字符串匹配算法
一开始写的string类里的find()函数超时了, 后来用的 < cstring>下的strstr() 函数也超时了
KMP 时间复杂度O(n)
strstr() 时间复杂度O(n^2)
.find() 时间复杂度O(m*n)
关于字符串匹配的效率 strstr 对比 KMP
KMP :
KMP算法最浅显理解——一看就明白
从头到尾彻底理解KMP
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#define mst(a) memset(a, 0, sizeof(a))
using namespace std;
const int maxn = 100000 + 10;
char s1[maxn], s2[maxn], ss[maxn];
int nxt[maxn];
bool kmp(int n, char* a, int m, char* b){
int i, j;
for( nxt[0] = j = -1, i = 1; i < n; nxt[i++] = j ){
while(~j && a[j+1] != a[i]) j = nxt[j];
if(a[j+1] == a[i]) j++;
}
for( j = -1, i = 0; i < m; i++ ){
while(~j && a[j+1] != b[i]) j = nxt[j];
if(a[j+1] == b[i]) j++;
if(j == n-1){
return true;
j = nxt[j];
}
}
return false;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%s%s",s1, s2);
int len1 = strlen(s1), len2 = strlen(s2);
if( strcmp(s2,"0") == 0 ){
printf("Alice\n");
continue;
}
if( strcmp(s1, s2) == 0 ){
printf("Alice\n");
continue;
}
if( len1 < len2 ){
printf("Bob\n");
continue;
}
if( kmp(len2, s2, len1, s1) )
printf("Alice\n");
else{
int i, j;
for( i = len2-1, j = 0; i >= 0; i--, j++ )
ss[j] = s2[i];
ss[j] = '\0';
//printf(" %s\n",ss);
if( kmp(len2, ss, len1, s1) )
printf("Alice\n");
else
printf("Bob\n");
}
}
return 0;
}