• 牛客练习赛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。














     
     
     
  • 相关阅读:
    C# 异常处理
    UIElement 的DesiredSize 和 RenderSize
    删除集合中满足条件的元素
    C# 中的Property
    C# readonly 与 const
    C# 实例化类的执行顺序
    C# volatile 与 lock
    双重检查加锁机制
    定位问题
    EBS部分表整理
  • 原文地址:https://www.cnblogs.com/lusiqi/p/11503206.html
Copyright © 2020-2023  润新知