zoukankan      html  css  js  c++  java
  • BZOJ2946 [Poi2000]公共串 【后缀自动机】

    题目

       给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
    

    任务:
    l 读入单词
    l 计算最长公共子串的长度
    l 输出结果

    输入格式

       文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
    

    输出格式

    仅一行,一个整数,最长公共子串的长度。
    

    输入样例

    3

    abcb

    bca

    acbc

    输出样例

    2

    题解

    经典的SAM求多串LCP
    首先对第一串建后缀自动机,然后用剩余的每一个串都在后缀自动机上跑一遍,分别得到后缀自动机上每个点的最大匹配长度
    最后每个点取每个串匹配长度的最小值,最大的那个点就是答案

    但要注意的是在parent树中,儿子的最大匹配值要向父亲传递,因为儿子所代表的位置集合是其父亲的真子集,父亲当然要包括儿子

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 4005,maxm = 100005,INF = 1000000000;
    int pre[maxn],ch[maxn][26],step[maxn],cnt,last,n;
    int g[maxn],f[maxn],a[maxn],b[maxn];
    char s[maxn];
    void ins(int x){
    	int p = last,np = ++cnt;
    	last = np; step[np] = step[p] + 1;
    	while (p && !ch[p][x]) ch[p][x] = np,p = pre[p];
    	if (!p) pre[np] = 1;
    	else {
    		int q = ch[p][x];
    		if (step[q] == step[p] + 1) pre[np] = q;
    		else {
    			int nq = ++cnt; step[nq] = step[p] + 1;
    			memcpy(ch[nq],ch[q],sizeof(ch[q]));
    			pre[nq] = pre[q]; pre[q] = pre[np] = nq;
    			while (ch[p][x] == q) ch[p][x] = nq,p = pre[p];
    		}
    	}
    }
    void topu(){
    	REP(i,cnt) b[step[i]]++;
    	REP(i,cnt) b[i] += b[i - 1];
    	REP(i,cnt) a[b[step[i]]--] = i;
    	REP(i,cnt) f[i] = step[i];
    }
    void walk(){
    	scanf("%s",s + 1); n = strlen(s + 1);
    	int u = 1,ans = 0,id;
    	REP(i,cnt) g[i] = 0;
    	for (int i = 1; i <= n; i++){
    		id = s[i] - 'a';
    		if (ch[u][id]) u = ch[u][id],g[u] = max(g[u],++ans);
    		else {
    			while (u != 1 && !ch[u][id]) u = pre[u];
    			if (u == 1) ans = 0;
    			else ans = step[u] + 1,u = ch[u][id],g[u] = max(g[u],ans);
    		}
    	}
    	for (int i = cnt; i; i--){
    		u = a[i];
    		if (pre[u]) g[pre[u]] = max(g[pre[u]],g[u]);
    		if (f[u] > g[u]) f[u] = g[u];
    	}
    }
    int main(){
    	int N; scanf("%d%s",&N,s + 1); N--;
    	cnt = last = 1; n = strlen(s + 1);
    	REP(i,n) ins(s[i] - 'a');
    	topu();
    	while (N--) walk();
    	int ans = 0;
    	REP(i,cnt) ans = max(ans,f[i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    grunt in webstorm
    10+ Best Responsive HTML5 AngularJS Templates
    响应式布局
    responsive grid
    responsive layout
    js event bubble and capturing
    Understanding Service Types
    To add private variable to this Javascript literal object
    Centering HTML elements larger than their parents
    java5 新特性
  • 原文地址:https://www.cnblogs.com/Mychael/p/8311118.html
Copyright © 2011-2022 走看看