您的位置:首页 > 其它

hdu 1238 KMP+枚举

2014-04-22 14:31 423 查看
杭电的课件上说这是入门级的题目,我真无语了,不为别的,只能怪自己笨。

先讲一讲我的解题思路,课件上写的很明白,总共有四个重点,前两个我自己可以独立搞定,这也是这一段时间以来自己可能进步的地方吧。接下来的两个问题可是有点棘手,如果暴力搜索的话,很有可能超时,其实自己写BF也挺费劲,由于以前写过kmp的知识,那么能不能在这里使用呢,看了下大神的代码,果真能用,于是翻出自己的陈年资料,看看自己如何转化到这里来。

这里不得不说一下kmp,我自己阅读自己以前的博客,发现自己的东西写的东西真的很差劲,只注重感性的抒发,没有可靠的理性说服力,于是,自己痛下决心,好好分享自己的东西,记住,如果没有价值,就不要发表。

回到正题,kmp先求next数组,在当时上数据结构的时候,对这个next就有些模糊,这个盲打真的很累阿。如‘aaba’初始值next【0】设置为0,然后从1开始对比,当然要设置一个k=0,如果str【i】==str【k】,就执行k++,在前面有一句很重要的语句当k》0且str【i】!=str【k】时,将next【k-1】赋给k。

接下来就是利用next【】计算kmp了,思想可能一样的。

硬性的知识可能就这些,接下来才是真正的编程经验。

如果你不确定一个字符串有多长,但你还想给它值并想使用,请最好使用memset(a,'\0',a)来使用,同时多要注意标志变量的使用,在前面的dfs中也是用一个特殊的标志变量来区别是否进栈。总之这个题目,可以让自己学到不少的东西。

***********************************************************************
File Name: 1238.cpp
Author: yubo
Mail: yuzibode@126.com
Created Time: 2014年04月21日 星期一 06时41分57秒
学习重点:
************************************************************************/

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>

using namespace std;
struct node{
char str[110];
int len;
}S[110],VER[110];
int next[110];
int cmp(const node&a,const node&b)
{
return a.len<b.len;

}
void getNext(char *str)
{
int len=strlen(str);
int k=0;
next[0]=0;
for(int i=1;i<len;i++){
while(k>0&&str[k]!=str[i])
k=next[k-1];
if(str[i]==str[k])
k++;
next[i]=k;
}
}
bool find(char *other,char *str)
{
int len=strlen(other);
int m=strlen(str);
int q=0;
for(int i=0;i<len;i++){
while(q>0&&str[q]!=other[i])
q=next[q-1];
if(str[q]==other[i])
q++;
if(q==m){
return true;
break;
}
}
return false;
}
main()
{
// freopen("A.IN","r",stdin);
int t,n;
char *sub;
char max[110];
scanf("%d",&t);
while(t--){
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%s",S[i].str);
S[i].len=strlen(S[i].str);
}
/*按字符串长度排序*/
sort(S,S+n,cmp);
/*将求反串*/
for(int i=0;i<n;i++)
{
int len=S[i].len;
for(int j=0;j<len;j++){
VER[i].str[j]=S[i].str[len-1-j];
}
VER[i].str[len]='\0';
}//反转过程很简单,写在另一个结构体数组中
//S[]是正向的,VER[]是反向的
// for(int i=0;i<n;i++)
// printf("%s\n",VER[i].str);
//临时字符串数组
char temp[110];
int pos;
memset(max,'\0',sizeof(max));
/*枚举正向的字串*/
for(int i=0;i<S[0].len;i++){
pos=0;
memset(temp,'\0',sizeof(temp));
for(int j=i;j<S[0].len;j++){
temp[pos++]=S[0].str[j];
//求next数组
getNext(temp);
int vis=1;
//与其他剩余的字串进行kmp比较
//正常理解就行
for(int k=0;k<n;k++){
if(!find(VER[k].str,temp)&&!find(S[k].str,temp)){
vis=0;
break;
}
}
if(vis&&strcmp(max,temp)<0)
memcpy(max,temp,sizeof(temp));
}
}
//枚举反向的子串
for(int i=0;i<S[0].len;i++){
pos=0;
memset(temp,'\0',sizeof(temp));
for(int j=i;j<S[0].len;j++){
temp[pos++]=VER[0].str[j];
getNext(temp);
int vis=1;
for(int k=0;k<n;k++){
if(!find(S[k].str,temp)&&!find(VER[k].str,temp)){
vis=0;
break;
}
}
if(vis&&strcmp(max,temp)<0)
memcpy(max,temp,sizeof(temp));
}
}

printf("%d\n",strlen(max));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  kmp 搜索