HDU-1238 - Substrings - KMP

链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=1238


题目:

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。


实现:

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值