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
题意: T组数据,每组数据给出n,表示接下来要输入n个字符串,定义字符串X满足对于给出的n个字符串,X要么为子串,要么为子串的逆序,求最长的X长度。
分析: 由于数据量很小,并且暴力匹配的时候也有很多剪枝,于是尝试一发哈希暴力匹配,没想到15ms过了......具体思路是先枚举第一个字符串的所有子串,对于每个子串再向下枚举,看第2~n个字符串是否存在某个子串能与枚举的第一个字符串的子串形成匹配。这样最坏情况下复杂度1e9,考虑几个需要剪枝的地方:枚举第一个串的子串时按长度降序枚举,这样找到的第一个符合要求的就是答案,直接退出就行。第一个串的子串长度最长应该是min(len[1], len[2], ......, len[n-1], len[n])。在和第i个字符串匹配时,如果存在子串匹配上了,直接break,如果不存在子串形成匹配,那接下来的字符串都不用去尝试匹配了。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define P 131
using namespace std;
char s[150][150];
unsigned long long h[150][150], p[150];
int len[150];
signed main()
{
int T;
cin >> T;
p[0] = 1;
for(int i = 1; i <= 149; i++)
p[i] = p[i-1]*P;
while(T--)
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
{
scanf("%s", s[i]+1);
len[i] = strlen(s[i]+1);
for(int j = 1; j <= len[i]; j++)
h[i][j] = h[i][j-1]*P+s[i][j];
}
int len1 = *min_element(len+1, len+1+n);
bool ans = false;//找到了答案标记为true
for(; len1 >= 1; len1--)//枚举第一个字符串的子串
{
for(int l = 1; l+len1-1 <= len[1]; l++)
{
int r = l+len1-1;
unsigned long long h1 = h[1][r]-h[1][l-1]*p[len1];//正序哈希值
unsigned long long h2 = 0;//逆序哈希值
for(int i = r; i >= l; i--)
h2 = h2*P+s[1][i];
for(int i = 2; i <= n; i++)//枚举2~n个字符串
{
bool flag = false;
for(int ll = 1; ll+len1-1 <= len[i]; ll++)
{
int rr = ll+len1-1;
unsigned long long hh = h[i][rr]-h[i][ll-1]*p[len1];
if(hh == h1 || hh == h2)
{
flag = true;
break;
}
}
if(!flag)
break;
if(i == n)//此时还没break说明找到了答案
{
printf("%d\n", len1);
ans = true;
break;
}
}
if(ans)
break;
}
if(ans)
break;
}
if(!ans)//如果没找到
puts("0");
}
return 0;
}