• 2018百度之星资格赛T2 子串查询


    【题解】

      很容易想到暴力做法:对于每个询问暴力查找区间内的最小字母,统计其出现次数。效率O(N^2),无法通过全部数据。

      我们可以换一个思路,设f[i][j]为第i个字母(字母‘A'到’Z'分别对应0到25)到第j个位置的出现次数和。

      对于每个询问[L,R],我们只要从0到25枚举每个字母,如果满足c[i][R]-c[i][L-1]>0,那么这个区间的这个字母出现过,输出其次数并break即可。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define LL long long
     5 #define rg register
     6 #define N 200010
     7 using namespace std;
     8 int T,t,n,m,l,r,ans,cnt[26][N];
     9 char c[N],mn;
    10 inline int read(){
    11     int k=0,f=1; char c=getchar();
    12     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    13     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    14     return k*f;
    15 }
    16 inline void Pre(){
    17     memset(cnt,0,sizeof(cnt));
    18 }
    19 int main(){
    20     T=t=read();
    21     while(T--){
    22         printf("Case #%d:
    ",t-T);
    23         Pre();
    24         n=read(); m=read();
    25         for(rg int i=1;i<=n;i++){
    26             c[i]=getchar();
    27             while(c[i]<'A'||c[i]>'Z') c[i]=getchar();
    28             cnt[c[i]-'A'][i]++;
    29         }
    30         for(rg int i=0;i<26;i++)
    31             for(rg int j=1;j<=n;j++) cnt[i][j]+=cnt[i][j-1];
    32         while(m--){
    33             l=read(),r=read();
    34             for(rg int i=0;i<26;i++) if(cnt[i][r]-cnt[i][l-1]>0){
    35                 printf("%d
    ",cnt[i][r]-cnt[i][l-1]);
    36                 break;
    37             }
    38         }
    39     }
    40     return 0;
    41 }
    42 Close
    View Code
  • 相关阅读:
    numpy 广播
    jupyter notebook
    OpenCV ——双线性插值(Bilinear interpolation)
    历届试题 大臣的旅费
    历届试题 幸运数
    数字图像处理_读写和显示图像
    历届试题 买不到的数目
    历届试题 连号区间数
    历届试题 翻硬币
    历届试题 剪格子
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9425979.html
Copyright © 2020-2023  润新知