题目:http://poj.org/problem?id=3450
题目大意:给你n个字符串,让你求出他们的最长公共子串,有多个时,输出字典序最小的,如果没有,就输出那句话。
和之前 poj 那道一样,暴力做,可是看复杂度好像很高的样子,poj 数据水了?。。。 = =
题目大意:给你n个字符串,让你求出他们的最长公共子串,有多个时,输出字典序最小的,如果没有,就输出那句话。
和之前 poj 那道一样,暴力做,可是看复杂度好像很高的样子,poj 数据水了?。。。 = =
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 4004;
const int MAX_LEN = 222;
int fail[MAX_LEN];
void get_fail(char *s)
{
int len = strlen(s);
int j = -1;
fail[0] = -1;
for(int i = 1;i<len;i++)
{
while(j>=0 && s[i] != s[j+1])
j = fail[j];
if(s[i] == s[j+1]) j++;
fail[i] = j;
}
}
int kmp(char *t,char *p)
{
int len_t = strlen(t);
int len_p = strlen(p);
get_fail(p);
int j = -1;
for(int i = 0;i<len_t;i++)
{
while(j >= 0 && t[i] != p[j+1])
j = fail[j];
if(t[i] == p[j+1]) j++;
if(j == len_p - 1) return 1;
}
return 0;
}
char str[MAXN][MAX_LEN];
char ans[MAX_LEN];
char tmp[MAX_LEN];
int main()
{
int n;
while(~scanf("%d",&n) && n)
{
int min_len = 222;
int min_str;
for(int i = 0;i<n;i++)
{
scanf("%s",str[i]);
int len = strlen(str[i]);
if(len < min_len)
{
min_len = len;
min_str = i;
}
}
int l = 1,r = min_len;
ans[0] = '\0';
while(l <= r)
{
int mid = (l+r) >> 1;
int ok = 0;
int first = 1;
for(int i = 0;i<min_len;i++)
{
int j = i + mid - 1;
if(j >= min_len) break;
int cnt = 0;
for(int k = i;k<=j;k++)
tmp[cnt ++] = str[min_str][k];
tmp[cnt] = '\0';
int flag = 1;
for(int k = 0;k<n;k++)
if(k != min_str)
{
if(!kmp(str[k],tmp))
{
flag = 0;
break;
}
}
if(flag)
{
ok = 1;
if(first || strcmp(ans,tmp) > 0)
{
strcpy(ans,tmp);
first = 0;
}
}
}
//printf("l = %d,r = %d,mid = %d\n",l,r,mid);
if(ok)
{
l = mid + 1;
}
else r = mid - 1;
}
if(ans[0] != '\0') puts(ans);
else puts("IDENTITY LOST");
}
return 0;
}