题目链接:http://codeforces.com/problemset/problem/519/D
题意分析:给定每个小写字母所对应的兴趣值,再给定一个字符串,求这个字符串中满足以下条件的子串的个数:长度大于等于2、首末字母相同、除首尾外中间字母兴趣值的和为0
解题思路:本题中涉及到区间和的问题。在每个数不再更改的情况下,一般直接记录每个位置的前缀和,就可以将区间和的问题转换为前缀和。这个题中,要求区间和为0且首尾相同的子串,我们只需求得当前字母之前相同字母,并且这些字母前缀和等于当前字母前缀和减去自己的兴趣值,这样的字母的个数就是以当前字母为末端的题中要求子串数。而要记录某一个数字出现多少次,很容易想到用map实现。
AC代码:
//CodeForces-19D A and B and Interesting Substrings //AC 2016-4-20 22:02:32 //trick prefix-sum #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cctype> #include <cstdlib> #include <cstring> #include <vector> #include <set> #include <string> #include <map> #include <queue> #include <deque> #include <list> #include <sstream> #include <stack> using namespace std; #define cls(x) memset(x,0,sizeof x) #define inf(x) memset(x,0x3f,sizeof x) #define neg(x) memset(x,-1,sizeof x) #define ninf(x) memset(x,0xc0,sizeof x) #define st0(x) memset(x,false,sizeof x) #define st1(x) memset(x,true,sizeof x) #define INF 0x3f3f3f3f #define lowbit(x) x&(-x) #define abs(x) (x>0?x:-x) #define max(x,y) (x>y?x:y) #define min(x,y) (x<y?x:y) #define bug cout<<"here"<<endl; //#define debug int val[26]; map<long long,long long> prefix[26]; char s[100007]; int main() { #ifdef debug freopen("E:\Documents\code\input.txt","r",stdin); freopen("E:\Documents\code\output.txt","w",stdout); #endif for(int i=0;i<26;++i) scanf("%d",&val[i]); long long cur=0; long long ans=0; char c=0; getchar(); while((c=getchar())!=' ') { c-='a'; if(prefix[c].count(cur)) ans+=prefix[c][cur]; cur+=val[c]; prefix[c][cur]++; } cout<<ans<<endl; return 0; }