zoukankan      html  css  js  c++  java
  • 2019南昌邀请赛网络预选赛

    传送门

    M. Subsequence(思维)

    题意

      给出一个只包含小写字母的字符串 $s$;

      接下来给你和 n 个 串 $t_{1,2,...,n}$,判断第 i 个串 $t_i$ 是否为 串 s 的子序列

      如果是,输出"YES",反之,输出"NO";

    •题解

      将 $s$ 中 26 个字母出现的位置分别记录下来;

      我放在了 vector<> 中;

    1 int n=strlen(s+1);///个人习惯,s下标从1开始
    2 for(int i=1;i <= n;++i)
    3     v[s[i]-'a'].push_back(i);

      假设当前要找的串 $t$ 长度为 m;

      那么,在匹配 $t_1$ 时,只需判断一下 $v[t_1 - 'a'].size()$ 是否大于 0 即可;

      如果 > 0 ,那么 $t_1$ 就匹配 $s$ 中的 $v[t_1 - 'a'][0]$ 位置;

      并定义 $pre=v[t_1 - 'a'][0]$,记录一下之前匹配好的位置;

      接下来匹配 $t_2$,类似 $t_1$ 的匹配;

      但是这次不仅要判断  $v[t_2 - 'a'].size()$ 是否大于 0,还需要找到 $v[t_2 - 'a']$ 是否存在 > pre 的值;

      因为 $t_2$ 在 $s$ 中匹配的位置势必要在 $t_1$ 之后,如果找到,更新 pre = $t_2$ 匹配的位置;

      然后,根据如上方式匹配 $t_2 , t_3 , cdots , t_m$;

      存在匹配不成功的地方,就返回 false;

      我是将这个匹配方式放到了 Find() 函数里的;

      定义数组 a,$a_i$ 表示 $'a'+i$ 字符在 v 中匹配到的位置;

     1 bool Find()
     2 {
     3     int m=strlen(t+1);
     4 
     5     mem(a,0);
     6     int pre=0;
     7     for(int i=1;i <= m;++i)
     8     {
     9         int x=t[i]-'a';
    10         ///在v[x]中查找第一个 > pre 的位置
    11         for(;a[x] < v[x].size() && v[x][a[x]] <= pre;a[x]++);
    12 
    13         ///匹配失败,返回false
    14         if(a[x] == v[x].size())
    15             return false;
    16         ///匹配成功,更新pre
    17         pre=v[x][a[x]];
    18     }
    19     return true;
    20 }

    •Code

      2019南昌邀请赛网络预选赛M.cpp

    坑点

      起初,Find() 函数里,在 v[x] 中查找第一个 > pre 的位置时我用的方法是在 v[x] 中二分查找;

    1 auto it=upper_bound(v[x].begin(),v[x].end(),pre);

      每次判断 it 是否为 v[x].end();

      一直TLE可还行;

      

      这种题就是用来卡二分的么,可记住了;

    •相似题(分割线:2019.6.21)

      类比Codeforces #565C 这道题,发现,这两道题有异曲同工之妙;

      首先,再分析一下本题的做法:

      在 s串中找 t串,如果找到,输出 "YES",反之,输出 "NO";

      如果将题意改为查找 s串 中最多有多少个 t串 呢?

      在类比一下Codeforces这道题,是不是发现两者的做法一样呢?

    •Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define memF(a,b,n) for(int i=0;i <= n;a[i++]=b);
     4 const int maxn=1e5+50;
     5 
     6 char s[maxn];
     7 char t[maxn];
     8 int a[30];
     9 vector<int >p[30];///存储字母在s中出现的位置
    10 
    11 char *Solve()
    12 {
    13     memF(a,0,29);
    14 
    15     int len=strlen(t+1);
    16     int cur=0;
    17     for(int i=1;i <= len;++i)
    18     {
    19         int index=t[i]-'a';
    20         for(;a[index] < p[index].size() && p[index][a[index]] <= cur;a[index]++);
    21         if(a[index] == p[index].size())
    22             return "NO";
    23         cur=p[index][a[index]];
    24     }
    25     return "YES";
    26 }
    27 void Init()
    28 {
    29     for(int i=0;i < 30;++i)
    30         p[i].clear();
    31     int len=strlen(s+1);
    32     for(int i=1;i <= len;++i)
    33         p[s[i]-'a'].push_back(i);
    34 }
    35 int main()
    36 {
    37     scanf("%s",s+1);
    38     Init();
    39 
    40     int test;
    41     scanf("%d",&test);
    42     while(test--)
    43     {
    44         scanf("%s",t+1);
    45         puts(Solve());
    46     }
    47     return 0;
    48 }
    View Code
  • 相关阅读:
    PHP中使用CURL实现GET和POST请求
    ecstore关于smarty语法调用
    Linux 定时任务详解
    fzu 1753 Another Easy Problem
    zoj 2562 More Divisors
    poj 2992 Divisors
    UVA10078多边形判断凹凸性
    UVA10002求凸包的质心
    UVA10088多边形内整点个数计算(计算几何)
    HDU 1824 简单2-sat
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10746691.html
Copyright © 2011-2022 走看看