hdu 1238 KMP+枚举

2 篇文章 0 订阅
杭电的课件上说这是入门级的题目,我真无语了,不为别的,只能怪自己笨。
先讲一讲我的解题思路,课件上写的很明白,总共有四个重点,前两个我自己可以独立搞定,这也是这一段时间以来自己可能进步的地方吧。接下来的两个问题可是有点棘手,如果暴力搜索的话,很有可能超时,其实自己写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));
	}	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值