[编程|1500分] 子串
时间限制:3秒
空间限制:32768K
空间限制:32768K
题目描述
给出一个正整数n,我们把1..n在k进制下的表示连起来记为s(n,k),例如s(16,16)=123456789ABCDEF10, s(5,2)=11011100101。现在对于给定的n和字符串t,我们想知道是否存在一个k(2 ≤ k ≤ 16),使得t是s(n,k)的子串。
输入描述:
第一行一个整数n(1 ≤ n ≤ 50,000)。 第二行一个字符串t(长度 ≤ 1,000,000)
输出描述:
"yes"表示存在满足条件的k,否则输出"no"
输入例子:
8 01112
输出例子:
yes
思路:
直接模拟出从1到N的2~16进制表示,然后暴力匹配即可。
注意进制数算完要逆过去呀。
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char a[3000050];
char b[1000050];
int nex[3000050];
int lena,lenb;
void set_naxt()//子串的nex数组
{
int i=0,j=-1;
nex[0]=-1;
while(i<lenb)
{
if(j==-1||b[i]==b[j])
{
i++; j++;
nex[i]=j;
}
else
j=nex[j];
}
}
int kmp()
{
int i=0,j=0;
set_naxt();
while(i<lena)
{
if(j==-1||a[i]==b[j])
{
i++;j++;
}
else
j=nex[j];
if(j==lenb)
return 1;
}
return 0;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
int ans=0;
scanf("%s",b);
lenb=strlen(b);
for(int jinzhi=2;jinzhi<=16;jinzhi++)
{
lena=0;
for(int i=1;i<=n;i++)
{
int cnt=0;
int tmp=i;
int num[100];
while(tmp)
{
num[cnt++]=tmp%jinzhi;
tmp/=jinzhi;
}
for(int j=cnt-1;j>=0;j--)
{
if(num[j]<10)
a[lena++]=num[j]+'0';
else a[lena++]=num[j]-10+'A';
}
}
ans=max(ans,kmp());
if(ans>0)break;
}
if(ans>0)printf("yes\n");
else printf("no\n");
}
}