题目:http://poj.org/problem?id=1226
题目大意:给你 n 个字符串,问你他们的最长公共子串的长度,加上不同的一点就是这个最长公共串可以倒序,就是倒序的也要去匹配,然后输出。
思路:基本思想就是先找到长度最小的字符串,然后枚举它的每个子串,判断另外 n - 1个字符串是不是含有,就这样。不过,其中要有优化,首先,其实前面那个找长度最小已经是一个优化了,然后长度用二分,匹配的时候用kmp,然后就OK了!
这道题好像数据不是很强,暴力也能过,匹配的时候不用kmp,直接用 strstr 也可以(虽然我以前不知道有这个函数)。。。 = =
说到这道题,真是说多了都是泪啊,就因为 get_fail 里那个 s[ j + 1] != s[ i ] 写成 == 了,然后 WA 了半天,自己造的数据竟然都是对的。。 T^T 另外,再提一点,这道题在hdu上也有,那个数据是真心水,怎么错的写的都是AC的,包括我这个 WA 的。。囧
题目大意:给你 n 个字符串,问你他们的最长公共子串的长度,加上不同的一点就是这个最长公共串可以倒序,就是倒序的也要去匹配,然后输出。
思路:基本思想就是先找到长度最小的字符串,然后枚举它的每个子串,判断另外 n - 1个字符串是不是含有,就这样。不过,其中要有优化,首先,其实前面那个找长度最小已经是一个优化了,然后长度用二分,匹配的时候用kmp,然后就OK了!
这道题好像数据不是很强,暴力也能过,匹配的时候不用kmp,直接用 strstr 也可以(虽然我以前不知道有这个函数)。。。 = =
说到这道题,真是说多了都是泪啊,就因为 get_fail 里那个 s[ j + 1] != s[ i ] 写成 == 了,然后 WA 了半天,自己造的数据竟然都是对的。。 T^T 另外,再提一点,这道题在hdu上也有,那个数据是真心水,怎么错的写的都是AC的,包括我这个 WA 的。。囧
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX_N = 111;
const int MAX_LEN = 111;
char str[MAX_N][MAX_LEN];
int fail[MAX_LEN];
void get_fail(char *s)
{
int len = strlen(s);
fail[0] = -1;
int j = -1;
for(int i = 1;i<len;i++)
{
while(j>=0 && s[j+1] != s[i]) j = fail[j];
if(s[j+1] == s[i]) j++;
fail[i] = j;
}
}
char inv[MAX_LEN],pri[MAX_LEN];
int kmp(char *s,int x)
{
get_fail(s);
int len1 = strlen(str[x]);
int len2 = strlen(s);
int j = -1;
for(int i = 0;i<len1;i++)
{
while(j >= 0 && s[j+1] != str[x][i]) j = fail[j];
if(s[j+1] == str[x][i]) j++;
if(j == len2-1) return 1;
}
return 0;
}
int main()
{
int _;
scanf("%d",&_);
while(_--)
{
int n;
scanf("%d",&n);
int min_len = MAX_LEN;
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 ans = 0;
int l = 1,r = min_len;
while(l <= r)
{
int len = (l + r) >>1;
int ok = 0;
for(int i = 0;;i++)
{
int j = i + len - 1;
if(j >= min_len) break;
int cnt = 0;
for(int k = i;k<=j;k++)
pri[cnt++] = str[min_str][k];
pri[cnt] = '\0';
cnt = 0;
for(int k = j;k>=i;k--)
inv[cnt++] = str[min_str][k];
inv[cnt] = '\0';
int flag = 1;
for(int x = 0;x<n;x++)
if(x != min_str)
{
if((!kmp(pri,x)) && (!kmp(inv,x)))
{
flag = 0;
break;
}
}
if(flag)
{
ok = 1;
break;
}
}
if(ok)
{
ans = len;
l = len + 1;
}
else r = len - 1;
}
printf("%d\n",ans);
}
return 0;
}
因为之前没有用过strstr,用了一下,尝尝鲜,上面的稍微改了一下,也写了一份:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX_N = 111;
const int MAX_LEN = 111;
char str[MAX_N][MAX_LEN];
int fail[MAX_LEN];
char inv[MAX_LEN],pri[MAX_LEN];
int main()
{
int _;
scanf("%d",&_);
while(_--)
{
int n;
scanf("%d",&n);
int min_len = MAX_LEN;
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 ans = 0;
int l = 1,r = min_len;
while(l <= r)
{
int len = (l + r) >>1;
int ok = 0;
for(int i = 0;;i++)
{
int j = i + len - 1;
if(j >= min_len) break;
int cnt = 0;
for(int k = i;k<=j;k++)
pri[cnt++] = str[min_str][k];
pri[cnt] = '\0';
cnt = 0;
for(int k = j;k>=i;k--)
inv[cnt++] = str[min_str][k];
inv[cnt] = '\0';
int flag = 1;
for(int x = 0;x<n;x++)
if(x != min_str)
{
if((!strstr(str[x],pri)) && (!strstr(str[x],inv)))
{
flag = 0;
break;
}
}
if(flag)
{
ok = 1;
break;
}
}
if(ok)
{
ans = len;
l = len + 1;
}
else r = len - 1;
}
printf("%d\n",ans);
}
return 0;
}