poj3080 枚举+ kmp

Problem:poj3080 枚举+ kmp
m 个子串的最长公共子串.
Analyse:
- 根据第一个串,枚举字串,然后对于后面的每一个用kmp来匹配,复杂度 O(n3m) .

/**********************jibancanyang************************** *Author* :jibancanyang *Created Time* : 二 5/10 13:18:53 2016 *File Name* : jy.cpp **Code**: ***********************[email protected]**********************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef unsigned long long ull;
vector<int> vi;
#define pr(x) cout << #x << ": " << x << " " 
#define pl(x) cout << #x << ": " << x << endl;
#define pri(a) printf("%d\n",(a));
#define xx first
#define yy second
#define sa(n) scanf("%d", &(n))
#define sal(n) scanf("%lld", &(n))
#define sai(n) scanf("%I64d", &(n))
#define vep(c) for(decltype((c).begin() ) it = (c).begin(); it != (c).end(); it++) 
const int mod = int(1e9) + 7, INF = 0x3fffffff;
const int maxn = 60 + 13;
char ans[maxn];
char s[11][maxn];
char p[maxn];
int ansv;

int nexts[maxn];
int cnt;

void getnexts(char *p) 
{
    nexts[0] = -1;
    int k = -1, j = 0, plen = cnt;
    while (j < plen - 1) {
        if (k == -1 || p[j] == p[k]) {
            k++, j++;
            if (p[j] != p[k]) nexts[j] = k;
            else nexts[j] = nexts[k];
        } else k = nexts[k];
    }
}

bool kmp(char *p, char *s)
{
    int i = 0, j = 0, plen = cnt, slen = strlen(s);
    while (j < plen && i < slen) {
        if (j == -1 || p[j] == s[i]) j++, i++;
        else j = nexts[j];
    }
    return j == plen;
}

int main(void)
{
#ifdef LOCAL
    freopen("/Users/zhaoyang/in.txt", "r", stdin);
    //freopen("/Users/zhaoyang/out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    sa(T);
    while (T--) {
        int n; sa(n);
        int minlen = INF;
        ansv = 2;
        ans[0] = '\0';
        for (int i = 0; i < n; i++) {
            scanf("%s", s[i]);
            minlen = min(minlen, (int)strlen(s[i]));
        }

        int len = strlen(s[0]);
        for (int i = 0; i < len; i++) {
            for (int j = i; j < len; j++) {
                if (j - i + 1 < ansv || j - i + 1 > minlen) continue;
                cnt = 0;
                for (int k = i; k <= j; k++) p[cnt++] = s[0][k];
                p[cnt] = '\0';
                getnexts(p);
                for (int k = 1; k < n; k++) {
                    if (!kmp(p, s[k])) break;
                    if (k == n - 1) {
                        if (j - i + 1 == ansv) {
                            if (strcmp(ans, p) > 0) memcpy(ans, p, sizeof(p)); 
                        }
                        if (j - i + 1 > ansv) memcpy(ans, p, sizeof(p)), ansv = j - i + 1;
                    }
                }

            }
        }
        if (ansv < 3) puts("no significant commonalities");
        else puts(ans);
    }
    return 0;
}

你可能感兴趣的:(poj3080 枚举+ kmp)