• [Wannafly挑战赛28][B msc和mcc][预处理+枚举]


    链接:https://ac.nowcoder.com/acm/contest/217/B
    来源:牛客网

    msc和mcc

    题目描述

    msc和mcc是一对好朋友,有一天他们得到了一个长度为n的字符串s.

    这个字符串s十分妙,其中只有’m’,’s’和’c’三种字符。

    定义s[i,j]表示s中从第i个到第j个字符按顺序拼接起来得到的字符串。

    定义一个字符串t的子序列为从t中选出一些位置并且将这些位置上面的字符按顺序拼接起来得到的字符串。

    两个子序列重合当且仅当存在一个位置x使得两个子序列同时选择了位置x。

    由于msc和mcc是一对很好很好的好朋友,所以她们希望选择两个数字x和y满足1≤x≤y≤n使得s[x,y]中同时存在两个**不重合的子序列**使得其中一个是’msc’且另外一个是’mcc’

    现在给出n和字符串s,问她们可以选出多少对不同的(x,y)。

    输入描述:

    第一行一个正整数n,表示字符串s的长度。

    第二行一个长度为n的字符串s,其中s只包含字符’m’,’s’和,’c’。(n<100000)

    输出描述:

    一行一个正整数,表示答案。
    题目大意:给一个字符串,求有多少个区间内部存在msc 和 mcc 两个子序列(并且二者不存在公共元素)
    题目分析:由于n是1e5级别的,并且是要对区间进行计数,所以只能在O(N)的时间复杂度下得到最终结果,可以想到枚举区间左端点O(N),然后就需要O(1)得到右端点的个数,右端点的个数也就是n-符合条件的最小右端点,所以这个时候只能预处理,而可以知道满足条件的长度为6的子序列只有8种,所以可以预处理出每种情况下的每一个元素后一个元素的位置,然后就能O(1)得到最小右端点了.
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<map>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 typedef long long ll;
     9 int n;
    10 char ch[8][7]={
    11     "012022",
    12     "010222",
    13     "001222",
    14     "002212",
    15     "022012",
    16     "020122",
    17     "020212",
    18     "002122"
    19 };
    20 int nx[100005][4],kt[100005];
    21 char s[100005];
    22 int main(){
    23     cin>>n;
    24     scanf("%s",s+1);
    25     for(int i=1;i<=n;i++){
    26         if(s[i]=='m')kt[i]=0;
    27         else if(s[i]=='s')kt[i]=1;
    28         else kt[i]=2;
    29     }
    30     for(int i=0;i<3;i++){
    31         int pos=n+1;
    32         for(int j=n;j>=0;j--){
    33             nx[j][i]=pos;
    34             if(kt[j]==i)pos=j;
    35         }
    36     }
    37     ll ans=0;
    38     for(int i=1;i<=n;i++){
    39         int ed=n+1;
    40         for(int j=0;j<8;j++){
    41             int pos=i-1;
    42             for(int k=0;k<6&&pos<=n;k++){pos=nx[pos][ch[j][k]-'0'];}
    43             ed=min(ed,pos);
    44         }
    45         ans+=n-ed+1;
    46     }
    47     cout << ans << endl;
    48     return 0;
    49 }
    View Code
    
    
    
     
  • 相关阅读:
    Java实现 LeetCode 450 删除二叉搜索树中的节点
    PHP mysqli_field_count() 函数
    PHP mysqli_fetch_row() 函数
    PHP mysqli_fetch_object() 函数
    PHP mysqli_fetch_lengths() 函数
    PHP mysqli_fetch_fields() 函数
    linux修改IP地址
    树莓派玩耍笔记2 -- 我的板子是正品么?(解答一些小问题)
    在一台server上部署多个Tomcat
    第十八篇:融汇贯通--谈USB Video Class驱动
  • 原文地址:https://www.cnblogs.com/MekakuCityActor/p/9943590.html
Copyright © 2020-2023  润新知