• cf519D . A and B and Interesting Substrings 数据结构map


    题意:

    已知26个小写字母有各自的权值(正,负,或0)

    现在给出一个字符串,长度<=1e5

    问这个字符串有多少个子串满足:

    开头的字母和结尾的字母一样

    字符串除了开头和结尾的字母外,其余的字母的权值和为0

    本来是一道水题,一看就知道大体的思路了,结果硬是搞了一个多小时

    先是用set,发现超时了,改为用map

    思路:

    1.我们先预处理这个字符串的权值的前缀和

    sum[i]表示从字符串的起点到i的权值和

    2.我们要找到的子串,设以l开头和r结尾,则有

    str[r] == str[l] 和 sum[r-1] - sum[l] == 0

    即:sum[r] - sum[l] == val[str[r] - 'a']

    那么我们只要记录:

    (char,sum)以0为开头,char为结尾,权值和为sum的子串的个数即可

    实现:用一个map

    遍历一遍字符串,对于每一个(char,sum),找到前面出现多少(char,sum-val[char-'a'])

    然后更新res,并且map[(char,sum)]++

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <set>
    #include <map>
    #include <cstdlib>
    
    #define LL long long
    #define fir first
    #define sec second
    
    using namespace std;
    
    int val[26];
    LL sum[100000+5];
    char str[100000+5];
    
    map< pair<char,LL>,int > ms;
    map< pair<char,LL>,int > :: iterator it;
    
    void solve()
    {
        for(int i=0;i<26;i++){
            scanf("%d",&val[i]);
        }
        scanf("%s",str);
        int len = strlen(str);
    
        ms.clear();
        LL res = 0;
        sum[0] = 0;
    
        for(int i=1;i<=len;i++){
            sum[i] = sum[i-1] + val[str[i-1] - 'a'];
        }
        
        pair<char,LL> pr;
        LL tmp;
        for(int i=1;i<=len;i++){
            pr = make_pair(str[i-1],sum[i]);
            it = ms.find(make_pair(pr.fir,pr.sec - val[pr.fir-'a']));
            if(it != ms.end())
                res += it->sec;
            ms[pr]++;
        }
    
        //printf("%lld
    ",res);
        printf("%I64d
    ",res);
        return ;
    }
    
    int main()
    {
        solve();
        return 0;
    }
  • 相关阅读:
    HTML编写需要注意的事项
    Java中this、super用法
    多态性的表现形式
    面向对象
    用java实现冒泡排序法
    第一堂java web课
    mysql 复制中的 paxso 的两阶段和事务两阶段的区别
    github删除仓库
    git的介绍及使用
    github的介绍
  • 原文地址:https://www.cnblogs.com/-maybe/p/5055893.html
Copyright © 2020-2023  润新知