题目链接:HDU1238
Substrings
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9192 Accepted Submission(s): 4353
Problem Description
You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.
Input
The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string.
Output
There should be one line per test case containing the length of the largest string found.
Sample Input
2 3 ABCD BCDFF BRCD 2 rose orchid
Sample Output
2 2
题意:给出一些字符串,问其中公共的最长子串的长度是多少,这里公共的子串是指子串本身或子串的反串在每个字符串中都出现过。
题目分析:可以先给字符串按长短排好序,然后枚举子串分别用正串和反串进行KMP,取最长的纪录长度。
这里也可以优化一下,比如正串失配再比较反串,KMP的函数可以整合到一起,不通过排序直接找长度最小的处理(不知道能不能变快),不过题目数据太弱了,怎么搞都是0ms,也没啥优化的必要。
//
// main.cpp
// HDU1238(1
//
// Created by teddywang on 16/5/13.
// Copyright © 2016年 teddywang. All rights reserved.
//
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct str{
char ss[110];
int len;
}s[110];
int next1[110],next2[110];
char t1[110],t2[110];
int n,m;
bool cmp(str a,str b)
{
if(a.len!=b.len)
return a.len<b.len;
else
{
return strcmp(a.ss,b.ss)<1;
}
}
void getnext(char *t1,char *t2)
{
int i=0,j=-1;
next1[0]=-1;next2[0]=-1;
int len=strlen(t1);
while(i<len)
{
if(j==-1||t1[i]==t1[j])
{
if(t1[++i]==t1[++j])
next1[i]=next1[j];
else next1[i]=j;
}
else j=next1[j];
}
i=0;j=-1;
while(i<len)
{
if(j==-1||t2[i]==t2[j])
{
if(t2[++i]==t2[++j])
next2[i]=next2[j];
else next2[i]=j;
}
else j=next2[j];
}
}
int kmp1(char *s,char *t)
{
int i=0,j=0;
int len1=strlen(s),len2=strlen(t);
while(i<len1&&j<len2)
{
if(j==-1||s[i]==t[j])
{
i++;j++;
if(j==len2) return 1;
}
else j=next1[j];
}
return 0;
}
int kmp2(char *s,char *t)
{
int i=0,j=0;
int len1=strlen(s),len2=strlen(t);
while(i<len1&&j<len2)
{
if(j==-1||s[i]==t[j])
{
i++;j++;
if(j==len2) return 1;
}
else j=next2[j];
}
return 0;
}
int main()
{
cin>>m;
while(m--)
{
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%s",s[i].ss);
s[i].len=strlen(s[i].ss);
}
sort(s,s+n,cmp);
int maxlen=0;
for(int i=0;i<s[0].len;i++)
{
int l=0;
for(int j=i+1;j<=s[0].len;j++)
{
int flag=0;
while(l<j-i)
t1[l++]=s[0].ss[i+l];
for(int k=0;k<l;k++)
t2[k]=t1[l-k-1];
t1[l]=t2[l]='\0';
getnext(t1,t2);
for(int k=1;k<n;k++)
{
if(kmp2(s[k].ss,t2)==0&&kmp1(s[k].ss,t1)==0)
{
flag=1;
break;
}
}
if(flag==1) break;
else if(l>maxlen)
maxlen=l;
}
}
cout<<maxlen<<endl;
}
}