您的位置:首页 > 其它

ACM练习之《自然的谜语》

2014-05-15 23:47 141 查看
然后说说我刷题之路遇到的第二题吧:《PID328/自然地谜语》。

5月13号中午,复习了string类后,用str.compare()函数很快搞定了这道题,哈哈,不过提交后只得了80分,显示TLE,百度:超出时间限制。看了一下最后两个测评超时了。。完全没接触过超时啊,这可怎么改。看了一下评论,貌似必须用一个KMP算法。。。艹,学!看不懂有木有。。。于是Google了好几个版本的教程,下到手机上,不断地看不断地研究……(顺便认识了一个BF算法,复习了指针一堆东西,引用等等。。好吧,我承认我TM快把去年学的东西忘光了。。。)

KMP学习文章一:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

KMP学习文章二:/article/4719933.html

KMP学习文章三:/article/5631720.html

附上BF与KMP练习代码:

#include <iostream>
#include <cstring>

using namespace std;

int KMPMatch(char *s,char *p);
int BFMatch(char *s, char *p);
void getNext(char *p,int *next);

int main()
{
char s1[11] = {'a','b','a','b','c','a','b','a','b','a'};
char s2[6] = {'a','b','a','b','c'};
cout << BFMatch(s1 , s2) << endl;
cout << KMPMatch(s1 , s2) << endl;
return 0;
}

//BF算法
int BFMatch(char *s , char *p)
{
int i,j;
i=0;
while(i<strlen(s))
{
j=0;
while(s[i]==p[j]&&j<strlen(p))
{
i++;
j++;
}

if(j==strlen(p))
return i-strlen(p);
i = i - j + 1 ;             //指针i回溯
}
return -1;
}

//KMP算法
int KMPMatch(char *s,char *p)
{
int next[100];
int i,j;
i=0;
j=0;
getNext(p,next);
while(i<strlen(s))
{
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else
{
j=next[j];       //消除了指针i的回溯
}
if(j==strlen(p))
return i-j;
}
return -1;
}

void getNext(char *p,int *next)
{
int j,k;
next[0]=-1;
j=0;
k=-1;
while(j<strlen(p)-1)
{
if(k==-1||p[j]==p[k])    //匹配的情况下,p[j]==p[k]
{
j++;
k++;
next[j]=k;
}
else                   //p[j]!=p[k]
k=next[k];
}
}


5月14号,带着稍稍能看懂那么一点的KMP算法,重写了这一题,提交检测成果……靠,服务器坏了 - -。








2014年5月16日23:46:25更新:

NND,服务器终于好了,TM一看竟然WA30,大失所望。排查出错误后再提交,最后三个测试点超时 - -。再改。又错。再改。又超时……

无奈了,问队友曹大神,果然他也WA了几次,哈哈。不过还是被他分分钟AC了 - -。看他的代码,感觉和我的差不多啊。。。郁闷。改来改去无效。放下不管了。。。

晚上,决定删了自己的代码仿着曹大神的重写,可是,竟然又有两道超时

。。。我可抄的就剩输入输出不一样了。。。换成他的输出函数,果然AC了。。。然后曹大神告诉我,cin和cout超级慢……(有时可在主函数使用 ios::sync_with_stdio(false);能加快速度)。

额额额,好吧,又涨姿势了:scanf + printf 要比 cin + cout 运行快。

唉,不管怎么说,今天终于算是把这道题解决了。看得出来我欠的知识实在太多,需要努力啊。

附上曹大神解此题的源代码:(很多地方值得我去学习



#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN = 100010,MAXM = 100010;
char T[MAXN],P[MAXM];
int Next[MAXM],N,M,C;
int Ans[MAXN];
void MakeNext(int M)
{
int i=0,j=-1;
Next[i] = -1;
while(i<M)
{
if(j==-1||P[i]==P[j])Next[++i] = ++j;
else j = Next[j];
}
}
int KMP(int pos,int N,int M)
{
int i = pos, j = 0,ans = 0;
while(i<N){
if(T[i]==P[j]||j==-1)i++,j++;
else j = Next[j];
if(j==M){
Ans[++ans]=i-j+1;
j = Next[j-1];
i--;
}
}
return ans;
}
int main()
{
scanf("%s%s",P,T);
N = strlen(T),M = strlen(P);
MakeNext(M);
int ans=KMP(0,N,M);
if(ans==0)
{
puts("There must be something wrong.");
return 0;
}
printf("%d\n",ans);
for(int i=1;i<=ans;i++)
printf("%d\n",Ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: