题目
UESTCOJ1510 渐变字符串
如果一个字符串,它每个字母(第一个除外)为前一个字母的后一位,则这样的字符串被称为“渐变字符串”。如:
“
a
b
c
d
e
”
,
"
h
i
j
k
l
m
n
o
p
q
r
"
“abcde”, "hijklmnopqr"
“abcde”,"hijklmnopqr"等等,你有
n
n
n个写有小写字母的卡片,你要将它们组成尽可能少的渐变字符串,卡片要全部用完,问:最少组成多少渐变字符串呢?
t
e
s
t
1
test 1
test1即样例,如果出现本机通过样例,提交出现wrong answer on test 1
的情况,请检查在
g
e
t
s
gets
gets或者
s
c
a
n
f
(
"
scanf("%c")
scanf("之前是否已经使用
g
e
t
c
h
a
r
(
)
getchar()
getchar()将上一行的空格吸收。
Standard Input
第一行一个数字
n
(
1
<
n
≤
1000
)
n(1<n \leq 1000)
n(1<n≤1000)
下面一行
n
n
n个小写字母
Standard Output
最少的渐变字符串数目
题解
如果用两重循环(字母表和字符串)来重复遍历字符串从而得到每一个连续字符,这样做不仅复杂度较高,而且在处理连续字符时并不轻松,所以用如下的思路来解题:
1、计数字符串中出现的字符(用数组)然后我们抛开来原理的字符串进行处理
2、用枚举第一个字母的方式入手,往后推到最大长度的字符串,怎么保证是连续字母呢?从计数数组中依次寻找所以能保证连续
3、在字符串长度大于0的情况下,枚举起点
s
t
a
r
t
start
start,前提该字母是不能为0个
4、在计数数组中依次寻找,如果下一个字母是0个,则退出寻找循环,如果不是0,则让这个字母数量减1
5、更新字符串长度
n
.
n.
n.
p
s
.
ps.
ps. 把字符
′
a
′
'a'
′a′转为
i
n
t
int
int数字1时更推荐使用:
s
[
i
]
−
′
a
′
+
1
;
s[i]-'a'+1;
s[i]−′a′+1;当然可以用
s
[
i
]
−
96
s[i]-96
s[i]−96,但是前一种不需要借助
A
S
C
I
I
ASCII
ASCII码表,可以直接减到0然后+1即可,方便理解和使用
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,alp[50],i,cnt=0;
memset(alp,0,sizeof(alp));
string s;
cin>>n>>s;
//计数每个字母(从a对应1开始)
for(i=0;i<n;i++){
alp[s[i]-96]++;
}
//枚举第一个字母,往后推到最大范围
while(n>0){
int start=1;//枚举起点的变量
while(alp[start]==0) start++;//如果该字母用完了,就从后面接着枚举
int t=start;//起点不可以随便改动,只能由上面一行代码让枚举继续
while(alp[t]!=0){
alp[t]--; t++;
}
cnt++;//找到一组计数器+1
n=n-(t-start);//更新字符串中字母数(注意t-start才是用过字母的数量)
}
cout<<cnt<<endl;
return 0;
}