题意:给你每个字符的权值,然后给你一个字符串,找出其中满足首尾字符相同,中间一段的字符之和为0的子串个数。
分析:看到题目中要求某一段字符之和为0,先求出1~n的连续和,用s[i]表示1~i的和是多少。从s[0]开始,在哈希表中查找是否有和他相同的值,若有则说明他们之间的这一段字符串之和为0,而且如果他们的首字母和尾字母相同,那么我们就找到了一种情况,并且把当前的s[i]插入到哈希表中,我们可以将具有相同和的项合并,用一个cnt记录当前和的个数,依次查找到s[n]就可以得到最终答案。
hash版:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int mod = 100007;
const int maxn = 1000007;
struct node{
long long key;
char alpha;//最后一个字母
int cnt;
int next;
node(){
next = 0;
cnt = 0;
}
};
struct hash{
int list[mod];
node v[maxn];
int v_cnt;//静态链表的元素数
hash(){
for(int i = 0; i < mod; i++)
list[i] = -1;
v_cnt = 0;
}
int hash_value(long long key){return key >= 0 ? key % mod:(-key) % mod ;}
void insert(long long key, char alpha);
int find(long long key,char alpha);
};
void hash::insert(long long key, char alpha){
int index = hash_value(key);
for(int i = list[index]; i != -1; i = v[i].next){
if(v[i].key == key && v[i].alpha == alpha){
v[i].cnt++;
return;
}
}
v[v_cnt].key = key;
v[v_cnt].alpha = alpha;
v[v_cnt].cnt = 1;
v[v_cnt].next = list[index];
list[index] = v_cnt;
v_cnt++;
}
int hash::find(long long key, char alpha){
int index = hash_value(key);
for(int i = list[index]; i != -1; i = v[i].next){
if(v[i].key == key && v[i].alpha == alpha){
return v[i].cnt;
}
}
return 0;
}
int al[26];
char s[100005];
long long sum[100005];
long long res = 0;
hash t;
int main(){
for(int i = 0; i < 26; i++)
scanf("%d",&al[i]);
scanf("%s",s);
//计算前n项和
int len = strlen(s);
sum[0] = al[s[0]-'a'];
for(int i = 1; i < len; i++)
sum[i] = sum[i-1] + al[s[i]-'a'];
t.insert(sum[0],s[0]);
for(int i = 1; i < len; i++){
res += t.find(sum[i-1],s[i]);
t.insert(sum[i],s[i]);
}
printf("%lld\n",res);
return 0;
}
看到大神代码改写的map版:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;
int al[26];
char s[100005];
long long sum[100005];
long long res = 0;
map<long long,long long> t[26];
int main(){
for(int i = 0; i < 26; i++)
scanf("%d",&al[i]);
scanf("%s",s);
//计算前n项和
int len = strlen(s);
sum[0] = al[s[0]-'a'];
for(int i = 1; i < len; i++)
sum[i] = sum[i-1] + al[s[i]-'a'];
t[s[0]-'a'][sum[0]]++;
for(int i = 1; i < len; i++){
res += t[s[i]-'a'][sum[i-1]];
t[s[i]-'a'][sum[i]]++;
}
printf("%lld\n",res);
return 0;
}
第一次这么用map~~