题目
题意:给定一个字符串
s
s
s,对于它的任意
(
t
,
u
,
v
)
(t,u,v)
(t,u,v),其中
t
t
t为
s
s
s的连续子串,
u
,
v
u,v
u,v为出现在
s
s
s的字符,如果
u
u
u在
t
t
t的出现次数与
v
v
v在
t
t
t的出现次数的差值的绝对值,恒小于等于1,则说明字符串
s
s
s是平衡的。现给定字符串
s
s
s,判断它是否为平衡的。
定理:定义 s s s中不同字符的个数为 k k k,长度为 n n n,如果对于任意的 0 < = i < n − k + 1 0<=i<n-k+1 0<=i<n−k+1,长度为 k k k的子串 s [ i , i + k − 1 ] s[i,i+k-1] s[i,i+k−1]上的字符都是不同的,则 s s s是平衡的。
必要性:如果存在子串 s [ i , i + k − 1 ] s[i,i+k-1] s[i,i+k−1]的字符有相同的,则 s s s至少有一个字符v没出现在子串 s [ i , i + k − 1 ] s[i,i+k-1] s[i,i+k−1]上,不妨设 s [ i , i + k − 1 ] s[i,i+k-1] s[i,i+k−1]的相同字符为 u u u,则有 c o u n t ( u ) − c o u n t ( v ) > = 2 count(u)-count(v)>=2 count(u)−count(v)>=2,因此 s s s是不平衡的。
充分性:如果对于任意的 0 < = i < n − k + 1 0<=i<n-k+1 0<=i<n−k+1,长度为 k k k的子串 s [ i , i + k − 1 ] s[i,i+k-1] s[i,i+k−1]上的字符都是不同的。对于任意的子串 s [ i , i + l − 1 ] s[i,i+l-1] s[i,i+l−1],它可以拆分成 ⌈ l / k ⌉ \lceil l/k\rceil ⌈l/k⌉段,除了最后一段,每一段上任意字符的出现次数都是1。因此任意字符,在子串 s [ i , i + l − 1 ] s[i,i+l-1] s[i,i+l−1]的出现次数为 ⌈ l / k ⌉ \lceil l/k\rceil ⌈l/k⌉,或者 ⌈ l / k ⌉ − 1 \lceil l/k\rceil-1 ⌈l/k⌉−1,因此,此时任意字符的在子串 s [ i , i + l − 1 ] s[i,i+l-1] s[i,i+l−1]的出现次数的差值的绝对值,小于等于1。因此, s s s是平衡的。
上述定理也可以转化为
s
s
s的前
k
k
k个字符不同,对于任意
i
>
=
k
i>=k
i>=k的字符,要求
s
i
=
=
s
i
−
k
s_i==s_{i-k}
si==si−k
官方代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int tc;
cin >> tc;
while(tc--)
{
string s;
cin >> s;
int n = s.length();
set<char> c;
bool ok = true;
int k;
for(k=0;k<n;k++)
{
if(c.find(s[k])==c.end())
c.insert(s[k]);
else
break;
}
for(int i=k;i<n;i++)
{
if(s[i]!=s[i-k])
ok = false;
}
if(ok)
cout << "YES\n";
else
cout << "NO\n";
}
}