纪念一次失败的暴力 统计回文字串

http://zju.acmclub.com/index.php?app=problem_title&id=1&problem_id=1054

我一向眼高手低,难题要啃半天,简单题常常不屑去做,有时候就想反正知道该怎么做了,就不会动手去敲代码。

渐渐我发现,我的同学他们敲代码的速度和出题效率比我高很多。慢慢发现,其实多做题哪怕是简单题,只要你坚持用自己的双手去敲代码,会极大提高自己对算法的分析能力和 把算法转化为代码的能力,这样可以帮助自己在解题时一气呵成,能够迅速完成初型,并进行检验和调试,

这些天做比赛,总碰到一些不好动手的题目结果是暴力解决,某种意义上,自己每次做题总是看着代码总结而不是看着题目总结,这导致我根本不能总结出有效的应对不同类型的题目的方法,题目常做常新,难以取得进步。

这不,夜深了,不好做难题,准备刷水题,结果碰到超时,还以为自己算法很了不起,原来是自己根本没动脑子或者没有经验。

这是我的超时代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[5050];
int judge(int x,int y)
{
for(int i=x;2*i<=x+y;i++)
{
if(s[i]!=s[x+y-i])return 0;//为1时为回文,为0时不是回文
}
return 1;
}
int cou,l;
int main()
{
while(~scanf("%s",s))
{
l=strlen(s);
cou=l;
for(int i=0;i<l;i++)
{
for(int k=i+1;k<l;k++)
{
if(judge(i,k))cou++;
}
}
printf("%d ",cou);
}
return 0;
}

这可以说是无脑型暴力,但是仔细一看,这代码其实是三层循环,复杂度相当的高,难怪会超时。

什么叫解题,转化+优化

找回文字符串的话,考虑到它有对称性,因此可以从中间向两边找。

//真是废柴,这种回文串的题目还没有一点经验
//回文串其实只有两种,一种长度为基数,以某一元素对称,第二种长度为偶数,中间有两个数
#include<cstdio>
#include<cstring>
#include<iostream>
char s[5050];
int l,cou,last,next;
int main()
{
while(~scanf("%s",s))
{
l=strlen(s);
cou=0;
for(int i=0;i<l;i++)
{
for(last=i,next=i;last>=0&&next<l;last--,next++)
{
if(s[last]==s[next])cou++;
else break;//这个else break,绝对不可以忘记,忘记不错
}
for(last=i,next=i+1;last>=0&&next<l;last--,next++)
{
if(s[last]==s[next])cou++;
else break;
}
}
printf("%d ",cou);
}
return 0;
}

这种代码算法清晰,循环简单,而且不容易出错,是真正的解题

哎,希望自己早日走出门外汉的尴尬。方法性总结,远比数目性刷题要强!

原文地址:https://www.cnblogs.com/plank-george-zzo/p/3218962.html