zoukankan      html  css  js  c++  java
  • String 尺取法

     1 #include <cstdio>
     2 #include <cstring>
     3 using namespace std;
     4 
     5 char s[1000010];  
     6 int vis[300];
     7 int main()
     8 {
     9     int tt,k,ss,t;  //ss 表示低的指针 t代表高的指针
    10     scanf("%d",&tt);
    11     while(tt--)
    12     {
    13         scanf("%s",s);
    14         scanf("%d",&k);
    15         ss=0;t=0;
    16         long long sum=0;
    17         int num=0;
    18         int len=strlen(s);
    19         memset(vis,0,sizeof(vis));
    20         for(;;)
    21         {
    22             while(t<len&&num<k)
    23             {
    24                 if(!vis[s[t]])
    25                 {
    26                     vis[s[t]]++;
    27                     num++;
    28                 }
    29                 else
    30                     vis[s[t]]++;
    31                 if(num>=k)      //如果子串不同字符大于k的退出
    32                     break;
    33                 t++;
    34             }
    35             if(num<k)       //退出后一种是大于不同字符退出,一种是到了最后len的时候退出,如第二种,则结束。
    36                 break;
    37             sum+=len-t;
    38             vis[s[ss]]--;
    39             if(!vis[s[ss]])     
    40             {
    41                 t++;
    42                 num--;
    43             }
    44             ss++;       //没找到一处,就使低指针加1;
    45         }
    46         printf("%lld
    ",sum);
    47     }
    48     return 0;
    49 }
    50             
    51         
    View Code

    有一个明显的性质:如果子串(i,j)包含了至少k个不同的字符,那么子串(i,k),(j<k<length)也包含了至少kkk个不同字符。

    因此对于每一个左边界,只要找到最小的满足条件的右边界,就能在O(1)O(1)O(1)时间内统计完所有以这个左边界开始的符合条件的子串。

    寻找这个右边界,是经典的追赶法(尺取法,双指针法)问题。维护两个指针(数组下标),轮流更新左右边界,同时累加答案即可。复杂度 O(length(S))

  • 相关阅读:
    Linux目录操作
    图形库
    Mybatis两表连接(一对一)
    ssm图片上传到数据库
    ajax函数实例
    html、css基础
    HDU 1213 How Many Tables
    HTML5简介
    在script中创建标签的三种方式
    html css js jq问题总结
  • 原文地址:https://www.cnblogs.com/WDKER/p/5446650.html
Copyright © 2011-2022 走看看