(AtCoder Beginner Contest 375)D - ABA
题目大意
给定一个只包含大写字母的字符串S,求解其长度为3的回文字序列个数
思路
首先暴力枚举区间计算答案
O
(
∣
S
∣
2
)
O(|S|^2)
O(∣S∣2) 一定是会超时的
我们考虑使用前缀和思想
我们对于每一个字母建立一个前缀和数组
设
c
n
t
[
i
]
[
j
]
cnt[i][j]
cnt[i][j] 表示字母
i
i
i 在前
j
j
j 个字符里面出现的次数
运用乘法原理,我们不难发现最后答案
a
n
s
ans
ans 可以这样计算
a
n
s
=
∑
i
=
1
26
∑
j
=
1
∣
S
∣
c
n
t
[
i
]
[
j
−
1
]
∗
(
c
n
t
[
i
]
[
n
]
−
c
n
t
[
i
]
[
j
+
1
]
)
ans={}\sum_{i=1}^{26}\sum_{j=1}^{|S|} cnt[i][j-1]*(cnt[i][n]-cnt[i][j+1])
ans=i=1∑26j=1∑∣S∣cnt[i][j−1]∗(cnt[i][n]−cnt[i][j+1])
时间复杂度为
O
(
26
∗
n
)
O(26*n)
O(26∗n) 姑且认为是
O
(
n
2
)
O(n^2)
O(n2)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define rep(i,x,y) for(ll i=x;i<=y;++i)
#define per(i,x,y) for(ll i=x;i>=y;--i)
using namespace std;
typedef long long ll;
const ll V=2e5+10;
char s[V];
ll n,dif[150][V],ans,p[500],maxn=-2,cnt[150][V];
inline ll in()
{
ll res=0,f=1;
char ch;
while((ch=getchar())<'0'||ch>'9')
if(ch=='-') f=-1;
res=res*10+ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return res*f;
}
inline void put(ll x)
{
if(x<0) putchar('-'),x*=-1;
if(x>9) put(x/10);
putchar(x%10+48);
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
rep(i,1,n)
{
ll x=s[i];
maxn=max(maxn,x);
++dif[x][i];
}
rep(i,1,maxn)
{
rep(j,1,n)
cnt[i][j]=cnt[i][j-1]+dif[i][j];
}
rep(i,1,maxn)
rep(j,2,n-1)
ans+=cnt[i][j-1]*(cnt[i][n]-cnt[i][j]);
printf("%lld",ans);
return 0;
}