题目连接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=72034#problem/D
给定a-z每个字母代表的数字,求共有多少个X。定义X:X为子序列,且最后一个与第一个字母相同,且其代表总和为0,不包含头尾。
Input
1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 7 1 1 1 8 1 1 1 1 1 1 xabcab
Output
2
Input
1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 7 1 1 1 8 1 1 1 1 1Output2
直接的想法是遍历,一个一个找与第i个字母相同且总和为0.但是时间有限制,于是就有,先把前n项的子串之和算出,存放哈希表中,只要找到与目前前缀和是否相同,在考虑他们对应最后一个字母是否相同即可。**************哈希可以缩短遍历时间,、子串和为0(a【i】.......a【j】),可以转化成前缀合s[j-1]-s[i]=0.
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #define T 100007 using namespace std; long long s[300000]; char str[300000]; struct node { char c; long long cnt; long long s; }tem; int get_hash(long long s) { if(s<0) s*=-7; return s%T; } vector<struct node > vec[T]; void insert(long long &s,char c) { int hash,len,i; hash=get_hash(s); len=vec[hash].size(); for(i=0;i<len;i++) { if(vec[hash][i].c==c&&vec[hash][i].s==s) { vec[hash][i].cnt++; break; } } if(i==len) { tem.cnt=1; tem.c=c; tem.s=s; vec[hash].push_back(tem); } } long long find(long long s,char c) { int hash,len,i; hash=get_hash(s); len=vec[hash].size(); for(i=0;i<len;i++) { if(vec[hash][i].c==c&&vec[hash][i].s==s) { return vec[hash][i].cnt; } } return 0; } int main() { int i,j,k,n,m,len; long long sum,cnt; int a[30]; while(scanf("%d",&a[0])!=EOF) { sum=0; for(i=0;i<T;i++) vec[i].clear(); for(i=1;i<26;i++) { scanf("%d",&a[i]); } scanf("%s",str); len=strlen(str); s[0]=a[str[0]-'a']; insert(s[0],str[0]); //printf("%d\n",s[0]); for(i=1;i<len;i++) { s[i]=s[i-1]+a[str[i]-'a']; //printf("%d %d\n",s[i],str[i]); cnt=find(s[i-1],str[i]); //printf("cnt=%d\n",cnt); sum+=cnt; insert(s[i],str[i]); } printf("%I64d\n",sum); } }
1aaa
#include<stdio.h>
#include<string.h>
#include<map>
using namespace std;
char str[300000];
map<long long ,int > my_map[30];
int main()
{
int i,j,k,l,len;
long long s,cnt;
int a[30];
while(scanf("%d",&a[0])!=EOF)
{
s=0;cnt=0;
for(i=1;i<26;i++)
scanf("%d",&a[i]);
scanf("%s",str);
len=strlen(str);
for(i=0;i<len;i++)
{
s+=a[str[i]-'a'];
//printf("%lld",s);
cnt+=my_map[str[i]-'a'][s-a[str[i]-'a']];
my_map[str[i]-'a'][s]++;
}
printf("%lld\n",cnt);
}
}