BZOJ2946 [Poi2000]公共串(後綴自動機)

Description

 
       給出幾個由小寫字母構成的單詞,求它們最長的公共子串的長度。
任務:
l        讀入單詞
l        計算最長公共子串的長度
l        輸出結果
 

Input

 
文件的第一行是整數 n,1<=n<=5,表示單詞的數量。接下來n行每行一個單詞,只由小寫字母組成,單詞的長度至少爲1,最大爲2000。
 

Output

僅一行,一個整數,最長公共子串的長度。
 

Sample Input

3
abcb
bca
acbc

Sample Output

HINT

 

Source

 

其實這題我沒A由於權限號密碼忘了 可是在COGS過了那就發一下吧。。  已ACspa

感受很zz啊,和單個串有什麼區別。code

那就直接把除了第一個串以外的SAM建出來而後枚舉第一個串暴力匹配求最小就行了blog

1Ahhhip

 

update:get

??爲何網上的題解都和我不同??string

這題好像只建一個SAM就好了??!!感受本身好菜啊。。。it

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 2001 * 2, INF = 1e9 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
struct SuffixAut {
    int fa[MAXN], len[MAXN], ch[MAXN][27], tot, last, root, ans, cur;
    SuffixAut() { cur = tot = last = root = 1; ans = 0;}
    void insert(int x) {
        int now = ++tot, pre = last; last = now;
        len[now] = len[pre] + 1;
        for(; pre && !ch[pre][x]; pre = fa[pre]) ch[pre][x] = now;
        if(!pre) fa[now] = root;
        else {
            int q = ch[pre][x];
            if(len[q] == len[pre] + 1) fa[now] = q;
            else {
                int nows = ++tot; 
                memcpy(ch[nows], ch[q], sizeof(ch[q]));
                fa[nows] = fa[q]; fa[q] = fa[now] = nows; len[nows] = len[pre] + 1;
                for(; pre && ch[pre][x] == q; pre = fa[pre]) ch[pre][x] = nows;
            }
        }
    }
    int work(int x) {
        if(ch[cur][x]) {cur = ch[cur][x]; ans++; return ans;}
        for(; cur && !ch[cur][x]; cur = fa[cur]);
        if(!cur) cur = root, ans = 0;
        else ans = len[cur] + 1, cur = ch[cur][x];
        return ans;
    }
}Suf[6];
char s[6][MAXN];
int N[6];
int main() {
#ifdef WIN32
    freopen("a.in", "r", stdin);
#else
    freopen("pow.in", "r", stdin);
    freopen("pow.out", "w", stdout); 
#endif    
    int num = read();
    for(int i = 1; i <= num; i++) scanf("%s", s[i] + 1), N[i] = strlen(s[i] + 1);
    for(int i = 2; i <= num; i++)
        for(int j = 1; j <= N[i]; j++)
            Suf[i].insert(s[i][j] - 'a');
    int out = 0;
    for(int i = 1; i <= N[1]; i++) {
        int ans = INF;
        for(int j = 2; j <= num; j++) 
            ans = min(ans, Suf[j].work(s[1][i] - 'a'));
        out = max(out, ans);
    }
    printf("%d", out);
    return 0;
}
相關文章
相關標籤/搜索