题目链接:https://www.lanqiao.cn/problems/499/learning/
总结:该题让我理解了字串的定义,并且懂得了如何搜索字串不会漏,不会重复,应该以 i 为字符头,自增,相当于字符头不断向右移,然后每确定一个 i ,就以它为字符头向右继续加字符,用 j 来代表向右加的字符,每加一个字符,则算一个新的字串。
代码与注解如下:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; int a[26];//一共26个字母,用一个一维数组表示其重复情况 int grade =0;//总分计分器 char str[100005]; int main() { cin>>str; int len=strlen(str); for(int i=0;i<len;i++){ //i的作用是确定从第几个字符开始枚举子字符串 memset(a,0,sizeof(a)); //每次要将a数组初始化为 0,因为每换一个 i 相当于重新开始,26个字母均没有出现过,所以全部赋值为 0 int score = 0; //记分 for(int j=i;j<len;j++){//j的变化相当于不断增加字符的个数形成新的字符串!!! //记住,从i开始增加字符哦,首字母一个一个随 i 向右移动!!! if(!a[(str[j]-'a')]){ //不是重复字符 grade+=(++score); //score加一分,并且这就算一个子字符串,然后将该子字符串的分加入总分 a[(str[j]-'a')]=1; //标记为已出现元素 }else{ //如果该字符已经出现过了,则此时重复了 if(score-1>=0){////如果本身分数都为 0,则遇到相同的还是为 0,不能将它减分!! score--; //则相当于新出现的字符发生重复,自然要取消之前这个字符加的一分 //所以这个新的字符串相对于上一个字符串来说,少了一个单独字母,则减一分 } grade+=score; //同样把这个新字符串的分数加入总分当中 } } } cout<<grade<<endl; return 0; }
代码和注解已经非常完备,充分理解此题优秀的加分思想,重复则减分,不重复则加分,但是当score>=1时发生重复才减分,因为如果一直都是重复的,则说明分数值就是为0,不能出现负分情况。
同时每加/或者减分/或者保持不变(此时必为0且发生重复的情况),都要将此时此刻的分值加入总分中,因为每次都代表其中一个字串的分值。
同时学会一个非常实用的数组赋值函数:memset
- 具体用法如下:
- 1.cstring
- 2.memset(数组名,值,sizeof(数组名));
- 3.只建议初学者使用memset赋值0或者-1。