Petrozavodsk Summer-2014. Andrew Stankevich Contest 46. J.Jingles of a String
题目大意
给你一个字符串,定义 $J(l, r)$ 为 $[l, r]$ 连续子串的字符集,定义 $S(J)$ 为 $J$ 的大小, $L(J)$ 为字符串中字符集为 $J$ 的连续子串的最长长度,求 $\sum{S(J)L(J)}$ 和 $J$ 的数量。
题目分析
考虑统计每一种 $J$ 的最长长度。从每一个字符作为起始字符入手,那么统计其之后的所有其他字符第一次出现的位置,这些情况对字符集中的字符做出了影响。可以使用 $26$ 个队列维护所有字符出现的位置,最后求解即可。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 1e5 + 5;
int n, m, t;
int cnt[(1 << 26) + 5];
char str[maxn];
long long ans;
vector <int> s;
struct ex {
int x;
int c;
};
bool cmp(ex x, ex y){
return x.x < y.x;
}
queue <int> q[30];
int main(){
int i, j;
scanf("%d", &t);
while(t--){
scanf("%s", str);
n = strlen(str);
for(auto i : s){
cnt[i] = 0;
}
s.clear();
ans = 0;
for(i=0;i<26;i++){
while(q[i].size()){
q[i].pop();
}
}
for(i=0;i<n;i++){
q[str[i] - 'a'].push(i);
}
for(i=0;i<n;i++){
vector <ex> vec;
for(j=0;j<26;j++){
if(q[j].size()){
vec.push_back((ex){q[j].front(), j});
}
}
vec.push_back((ex){n, str[i] - 'a'});
sort(vec.begin(), vec.end(), cmp);
int tmp = (1 << vec[0].c);
int c = 1;
for(j=1;j<vec.size();j++){
if(!cnt[tmp]){
s.push_back(tmp);
}
if(cnt[tmp] < vec[j].x - i){
ans += (vec[j].x - i - cnt[tmp]) * c;
cnt[tmp] = vec[j].x - i;
}
tmp |= (1 << vec[j].c);
c++;
}
q[str[i] - 'a'].pop();
}
printf("%d %lld\n", (int)s.size(), ans);
}
return 0;
}