题目链接:https://acm.njupt.edu.cn/problem/NOJ2452
题意:给定一个字符串,求它有多少个子字符串中包含sad序列
解题思路:
①先找出每一组字串[i,j],a[i]=‘s’,a[j]=‘d’,并且[i,j]中包含一个点a[k]=‘a’。使用的方法是找到每一个‘a’的前面最近的’s’,和后面最近的’d’
②处理字符串中的每一个’a’,求出所有包含sad的最短字串,对于相同的L,取R最小的保存
③枚举左端点,每次让当前字串包含一个最近的sad字串即可,统计贡献。
#define _CRT_SECURE_NO_WARNING
#include<iostream>
#include<cstdio>
#include<string.h>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
const int maxn = 2e6 + 10;
#define ll long long
string s;
int pre[maxn];
int Next[maxn];
ll ans;
struct node {
int l;
int r;
};
vector<node> v;
int main() {
cin >> s;
int sz = s.size();
int p1=-1, p2=-1;
for (int i = 0; i < sz; i++) {
if (s[i] == 's') {
p1 = i;
}
if (s[i] == 'a') {
pre[i] = p1;
}
}
for (int i = sz; i >= 0; i--) {
if (s[i] == 'd') {
p2 = i;
}
if (s[i] == 'a') {
Next[i] = p2;
}
}
for (int i = 0; i < sz; i++) {
if(s[i]=='a'){
if (pre[i] != -1 && Next[i] != -1) {
node tmp; tmp.l = pre[i]; tmp.r = Next[i];
v.push_back(tmp);
}
}
}
int sz1 = v.size();
int cnt = 0;
int pre1 = -1;
if (sz1 == 0) {
cout << 0 << endl;
return 0;
}
for (int i = 1; i < sz1; i++) {
if (v[i].l == v[i-1].l) {
if (v[i].r < v[cnt].r) {
v[cnt].r = v[i].r;
}
}
else {
v[++cnt].l = v[i].l;
v[cnt].r = v[i].r;
}
}
for (int i = 0; i <= cnt; i++) {
int L = v[i].l;
int R = v[i].r;
ans += (ll)(L - pre1) * (ll)(sz - R);
pre1 = L;
}
cout << ans << endl;
return 0;
}