zoukankan      html  css  js  c++  java
  • 牛客练习赛51 B 子串查询 https://ac.nowcoder.com/acm/contest/1083/B

    题目描述

    给出一个长度为n的字符串s和q个查询。对于每一个查询,会输入一个字符串t,你需要判断这个字符串t是不是s的子串。子串的定义就是存在任意下标a<b<c<d<e,那么”s[a]s[b]s[c]s[d]s[e]”就构成s的一个子串。如”abc”的子串有”a”、”b”、”c”、”ab”、”ac”、”bc”、”abc”。

    输入描述:

    第一行两个数n,q。1<=n,q<=1e5。

    第二行一个长度为n的字符串s,所有字符都为小写拉丁字符。

    接下来q行每行一个字符串t。1<=|t|<=50。

    输出描述:

    对于每个查询,如果t是s的字串,输出”YES”,否则输出”NO”。每个答案占一行。
    示例1

    输入

    复制
    8 4
    ababcbaa
    abac
    accb
    aaaa
    abcba

    输出

    复制
    YES
    NO
    YES
    YES

    ac代码:
    方法一:
    #include<bits/stdc++.h>
    using namespace std;
    int n,q,i,pos,f;
    string s,a;
    int main(){
        cin>>n>>q>>s;
        while(q--){
            cin>>a;
            pos=0;
            f=1;
            for(int i=0;i<a.length()&&f;i++){
                auto it = s.find(a[i],pos);
                if(it==s.npos) f=0;
                else
                    pos = it+1;//要查找下一个,所以+1
            }
            if(f)
                cout<<"YES"<<endl;
            else
                cout<<"NO"<<endl;
        }
         
        return 0;
    }
     
    解析:
    方法原型描述
    size_type find(const string & str, size_type pos = 0) const 从字符串的pos位置开始,查找子字符串str。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回string::npos
    size_type find(const char * s, size_type pos = 0) const 从字符串的pos位置开始,查找子字符串s。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回string::npos
    size_type find(const char * s, size_type pos = 0, size_type n) const 从字符串的pos位置开始,查找s的前n个字符组成的子字符串。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回string::npos
    size_type find(const char ch, size_type pos = 0) const 从字符串的pos位置开始,查找字符ch。如果找到,则返回该子字符串首次出现的位置;否则,返回string::npos
     
     
    方法二:
    #include<bits/stdc++.h>
    using namespace std;
    int N,Q,a[30],n[30],b[100005][30];
    string s;
    int main(){
        cin>>N>>Q;
        cin>>s;
        int len = s.length();
        memset(n,-1,sizeof(n));
        for(int i = len-1;i>=0;i--){
            int x = s[i]-'a';//相当于把字符转换为数字a就是0,b就是1,以此类推
            for(int j=0;j<26;j++){
                b[i][j] = n[j];
            }
            n[x] = i;
        }
        for(int i=1;i<=Q;i++){
            string q;
            cin>>q;
            int cg = q.size();//这里我用q.length()就会超时;
            int iq = 0,is,cnt = 0;
            while(iq<len&&cnt<cg){
                if(cnt==0) iq = n[q[0]-'a'];
                else{
                    if(b[iq][q[cnt]-'a']!=-1)
                        iq = b[iq][q[cnt]-'a'];
                    else
                        break;
                }
                cnt++;    
            }
            if(cnt == cg) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }    
        return 0;
    }
     
    思路:
    这个很巧
    就拿这个例子来说:
     0 1 2 3 4 5 6 7
    a b a b c b a a
    a b a c
    b[7][0 - 25]= -1; n[0]=7;

    b[6][0] = 7;b[6][1-25]=-1; n[0]=6;

    b[5][0]=6,b[5][1-25]=-1; n[1] = 5;

    b[4][0]=6,b[4][1]=5,b[4][2-25]=-1; n[2] = 4;

    //当遍历到c时,b[4][0]记录的是最先的a(0代表a)的位置,b[4][1]记录的是最先的b的位置
    ...
    i从后往前是为了统计当从这个字母开始(不包括这个字母)后面的字母的位置,n中0就代表a,1就代表b,

    然后这样就可以统计记录整个表的情况,如果是i从前遍历就不能做到

    下面判断当cnt==0时要单独拿出来,就是因为当遍历到这个字母时,统计是不包括这个字母的。

    b有len层,相当于在跳层的验证是否这个位置是存了数的,如果是-1就相当于没有这个数,就跳出循环输出NO。














     
     
     
  • 相关阅读:
    Encryption (hard) CodeForces
    cf 1163D Mysterious Code (字符串, dp)
    AC日记——大整数的因子 openjudge 1.6 13
    AC日记——计算2的N次方 openjudge 1.6 12
    Ac日记——大整数减法 openjudge 1.6 11
    AC日记——大整数加法 openjudge 1.6 10
    AC日记——组合数问题 落谷 P2822 noip2016day2T1
    AC日记——向量点积计算 openjudge 1.6 09
    AC日记——石头剪刀布 openjudge 1.6 08
    AC日记——有趣的跳跃 openjudge 1.6 07
  • 原文地址:https://www.cnblogs.com/lusiqi/p/11503206.html
Copyright © 2011-2022 走看看