首页 > 代码库 > CodeM初赛B轮
CodeM初赛B轮
做什么啊,我这么菜,应该弃赛的
[编程|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
这个题很简单啊,这一场的手速题
暴力枚举KMP就好了,我想到了KMP但是没有从网上找模板,找到模板发现自己还是想的不好,最后优化成了这个样子,自我感觉还是很完美的
长度 ≤ 1,000,000,这个也是给我开数组的提示,竟然不坑,反正觉得2进制的1到50k还是不小的
#include <bits/stdc++.h> using namespace std; char s[1000005],t[1000005]; int nex[1000005]; int l; char f[20]; void la(int n, int b) { static char c[16]= {‘0‘,‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘,‘8‘,‘9‘,‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘}; l=0; while(n) { f[l++]=c[n%b]; n=n/b; } } void pre(char *p) { int i,n,k; n=strlen(p); nex[1]=nex[0]=0; k=0; for (i=2; i<=n; i++) { for(; k!=0&&p[k]!= p[i-1]; k=nex[k]); if(p[k]==p[i-1])k++; nex[i]=k; } } int kmp(char *text, char *p) { int m,n,s,q; m=strlen(p); n=strlen(text); q=s=0; while (s<n) { for (q=nex[q]; q<m&&p[q]==text[s]; q++,s++); if (q== 0) s++; else if(q==m) { return 1; } } return 0; } int main() { int n; scanf("%d",&n); getchar(); for(int i=0; ; i++) { char c=getchar(); if(c==‘\n‘) { t[i]=0; break; } t[i]=c; } pre(t); for(int j=16; j>1; j--) { int b=0; for(int i=1; i<=n; i++) { la(i,j); for(int k=l-1; k>=0; k--) s[b++]=f[k]; } s[b]=0; if(kmp(s,t)) return 0*puts("yes"); } return 0*puts("no"); }
CodeM初赛B轮
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。