给定k个限制条件,其中第i个条件用c[i],l[i],r[i]表示:
字符c[i]在字符串中的出现次数大等于l[i],小等于r[i]。
若一个字符串满足的限制条件的个数大等于L,小等于R,则称该串为Stenis String
给定一小写字母串s,求s有多少个子串是Steins String。
对于100%的数据 0<=L<=R<=k<=500,0<=l[i]<=r[i]<=|s|,|s|<=10^5
-------------------------------------------------华丽的分割线---------------------------------------------------------
解题报告:
做法很显然是枚举右端点,然后维护 [i, nowr](i = 1, 2, ..., nowr) 的满足条件个数。
我们先考虑只有一个条件的情况。
这很显然就是要维护[i, nowr]中规定字母出现次数,
然后相关条件的合法性也就随之而生了。
其中每个格子只会被弄两次:
第一次:将其标记为符合条件,
第二次:将其标记为不符合条件,
可以保证之后再也不会处理这个格子了。
好的,现在有很多个条件了,
那就直接暴力处理每一个条件,
然后每个格子只会被处理 (2 * 条件个数) 次。
于是这整个题目就可以在 O(k * |s|) 的时间内做完了。
然后还有各种各样的细节要处理……
My code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define N 100000 + 5
#define K 500 + 5
int len, n, L, R, Pointer_Size[K], Pos_Size[K], A[K][3], Total[N];
LL res, ans;
vector <int> Pointer[K];
vector <int> Pos[K];
char s[N];
int main()
{
scanf("%s", s);
len = strlen(s);
scanf("%d%d%d", &n, &L, &R);
for (int i = 1; i <= n; i ++)
{
char ch[9];
memset(ch, '\0', sizeof(ch));
scanf("%s%d%d", ch, A[i] + 1, A[i] + 2);
A[i][0] = ch[0] - 'a';
Pointer_Size[A[i][0]] ++;
Pointer[A[i][0]].push_back(i);
}
for (int i = 0; i < 26; i ++)
Pos[i].push_back(-1);
for (int i = 0; i < len; i ++)
{
if (L <= 0 && 0 <= R) ans ++;
int j = s[i] - 'a';
Pos_Size[j] ++;
Pos[j].push_back(i);
for (int k = 1; k <= n; k ++)
if (A[k][1] == 0)
{
Total[i] ++;
if (Total[i] == L) ans ++;
else if (Total[i] == R + 1) ans --;
}
for (int k = 0; k < Pointer_Size[j]; k ++)
{
if (Pos_Size[j] >= A[Pointer[j][k]][1] && A[Pointer[j][k]][1] > 0)
{
for (int p = Pos[j][Pos_Size[j] - A[Pointer[j][k]][1]] + 1; p <= Pos[j][Pos_Size[j] - A[Pointer[j][k]][1] + 1]; p ++)
{
Total[p] ++;
if (Total[p] == L) ans ++;
else if (Total[p] == R + 1) ans --;
}
}
if (Pos_Size[j] > A[Pointer[j][k]][2])
{
for (int p = Pos[j][Pos_Size[j] - A[Pointer[j][k]][2] - 1] + 1; p <= Pos[j][Pos_Size[j] - A[Pointer[j][k]][2]]; p ++)
{
Total[p] --;
if (Total[p] == L - 1) ans --;
else if (Total[p] == R) ans ++;
}
}
}
res += ans;
}
cout << res << endl;
return 0;
}