题目地址:https://ac.nowcoder.com/acm/problem/13253

题目描述 


给出一个正整数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"
示例1
输入
8
01112
输出
yes

解题思路:


把1~n转化成对应的2~16进制序列,再在该序列中查找是否存在字符串t

进制转化方法:

1.用int数组存对应的进制序列,再将int数组转化为char[],分0~9和10~15两中情况转化成对应的字符,获得最终进制序列

2.用string存转化后的最终进制序列,利用string的+操作(int->char的转变)

寻找子串方法:

1.kmp算法

2.如果用的是string存最终进制序列,则可以使用string.find(t)!=string::npos判断存在,时间复杂度为O(n*m),这种方法在这道题里不会超时。也可以使用kmp,时间复杂度为O(n+m)

ac代码:


string+string.find()

#include <bits/stdc++.h>
#define maxn 5005
#define inf 0x3fffffff
using namespace std;
typedef long long ll;
char to_des(int x)
{

    if(x>=0&&x<=9)
        x=x+'0';
    else if(x>=10&&x<=15)
        x=x-10+'A';
    return (char)x;
}
string num_to_string(int des,int num)
{
    string a;
    while(num>0)
    {
        int x=num%des;
        a=to_des(x)+a;
        num/=des;
    }
    return a;
}
int n;
string t;
int main()
{
    scanf("%d", &n);
    cin >> t;
    bool flag = false;
    for (int i = 2; i <= 16; i++)
    {
        string s;
        for (int j = 1; j <= n; j++)
            s+= num_to_string(i, j);
        if (s.find(t) != string::npos) {
            flag = true;
            break;
        }
    }
    if (flag) printf("yes");
    else printf("no");
    return 0;
}

string+kmp()

#include <bits/stdc++.h>
#define maxn 1000005
#define inf 0x3fffffff
using namespace std;
typedef long long ll;
int Next[maxn];
int n;
string t;
char to_des(int x)
{
    if(x>=0&&x<=9)
        x=x+'0';
    else if(x>=10&&x<=15)
        x=x-10+'A';
    return (char)x;
}
string num_to_string(int des,int num)
{
    string a;
    while(num>0)
    {
        int x=num%des;
        a=to_des(x)+a;
        num/=des;
    }
    return a;
}
void set_Next()
{
    int j=0,k=-1;
    Next[0]=-1;
    while(j<t.length()-1)
    {
        if(k==-1||t[j]==t[k])
        {
            j++;k++;
            Next[j]=k;
        }
        else k=Next[k];
    }
}
int kmp(string s,string t)
{
    int i=0,j=0;
    while(i<s.length() || j<t.length())
    {
        if(j==-1 || s[i]==t[j])
        {
            i++;j++;
        }
        else
            j=Next[j];
        if(j==t.length()) return 1;
    }
    return 0;
}
int main()
{
    scanf("%d", &n);
    cin >> t;
    set_Next();
    bool flag = false;
    for (int i = 2; i <= 16; i++)
    {
        string s;
        for (int j = 1; j <= n; j++)
            s+= num_to_string(i, j);
        if(kmp(s,t))
        {
            flag = true;
            break;
        }
    }
    if (flag) printf("yes");
    else printf("no");
    return 0;
}

int[]+char[]+kmp  来源:https://me.csdn.net/mengxiang000000

#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");
    }
}