您的位置:首页 > 其它

POJ 1226 Substrings 暴力枚举+KMP算法

2012-07-07 11:28 399 查看
/*题意就是给你若干字符串,找出这些字符串中最大的相同字母个数,正逆序都可以。

想法是,因为必须是每个字符串中共有的部分,所以可以随便拿一个字符串来枚举他的子串。

我拿了a[1].然后枚举他不同长度的子串。

从大到小,如果KMP(子串,原串(2-n))||(KMP(逆序子串,原串(2-n)))成立的话,则该子串就是最大相同子串,因为是从大到小枚举的直接输出该串长度,结束。*/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2005
#define inf 1<<28
using namespace std;
char a[Max][Max];
int next[Max],n;

void findnext(char a[])
{
int k=-1;
int j=0;
next[0]=-1;
int l=strlen(a);
while(j<l)
{
if(k==-1||a[k]==a[j])
{
k++,j++;
next[j]=k;
}
else k=next[k];//当前缀字符与后缀字符不相等时返回前一状态
}
}

int KMP(char a[],char b[])
{
findnext(a);
int posa=0,posb=0;
int la=strlen(a),lb=strlen(b);
while(posa<la&&posb<lb)
{
if(posa==-1||a[posa]==b[posb])
{
posa++,posb++;//当匹配成功时,两个字符串各后移一个字符
}
else posa=next[posa];
}
if(posa<la)return 0;//匹配失败
//当匹配成功的时候posa的指针应该指向a字符串的最后一个字符+1处,也就是la处
else return 1;//匹配成功,若返回首地址可以写return posb-posa;
}

int main()
{
int i,j,k,l,m,T;
char reva[Max],revb[Max];
cin>>T;
while(T--)
{
int min_i=-1;
int min_l=1000;
cin>>n;
for(i=1; i<=n; i++)
{
scanf("%s",a[i]);//网上看到一种写法就是直接在这一步中找出长度最小的原串,然后枚举该串。多一个比较的步骤,但是时间应该比我这个快

}
l=strlen(a[1]);
bool flag=0;//标记未找到最大子串
for(i=l;i>0;i--)//从最大子串开始枚举
{
for(j=0;j<l-i+1;j++)//枚举的次数
{
int count=0;
for(k=j;k<=j+i-1;k++)//本次枚举的正序串
reva[count++]=a[1][k];
reva[count]='\0';
count=0;
for(k=j+i-1;k>=j;k--)//本次枚举的逆序串
revb[count++]=a[1][k];
revb[count]='\0';
count=0;
for(k=2;k<=n;k++)//是否与每一个原串都匹配
{
if(KMP(reva,a[k])||KMP(revb,a[k]))
count++;
}
if(count==n-1)//count=n-1则全部匹配,输出子串的长度即为答案
{
flag=1;
cout<<strlen(reva)<<endl;
break;
}
}
if(flag)
break;
}
if(!flag)
cout<<0<<endl;

}
return 0;
}


考察KMP的应用以及子串的构造。枚举居然没超时。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法