HDU-1238 - Substrings - KMP

题目：

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.

2
3
ABCD
BCDFF
BRCD
2
rose
orchid

2
2

题意：

在给定的字符串或其反转串中找到最长公共子串。

暴力KMP。

实现：

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 207;
int jump[maxn];
void process(char *p, int len) {
int i = 0, j = jump[0] = -1;
while(i < len) {
if(j < 0 || p[i] == p[j]) {
i++, j++;
jump[i] = (p[i] == p[j] ? jump[j] : j);
} else j = jump[j];
}
}
bool kmp(char *s, int ls, char *p, int lp) {
int i = 0, j = 0;
while(i < ls && j < lp) {
if(j < 0 || s[i] == p[j]) i++, j++;
else j = jump[j];
}
return j == lp;
}
char s[maxn][maxn];
int main() {
int len[maxn], t, n; scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i=0 ; i<n ; i++) {
scanf("%s", s[i]), len[i] = int(strlen(s[i]));
for(int p = 0, q = len[i]-1 ; p <= q ; p++, q--)
s[i+n][q] = s[i][p], s[i+n][p] = s[i][q];
}
int tmp = len[0]+1, len0 = len[0];
bool flag = false;
while(!flag && --tmp > 0) {
for(int l = 0, r = tmp-1 ; r < len0 && !flag ; l++, r++) {
flag = true;
process(s[0]+l, r-l+1);
for(int i = 1 ; i < n && flag ; i++) {
if(kmp(s[i], len[i], s[0]+l, tmp) || kmp(s[i+n], len[i], s[0]+l, tmp)) continue;
flag = false;
}
}
}
printf("%d\n", tmp);
}
return 0;
}