zoukankan      html  css  js  c++  java
  • [BZOJ2946][Poi2000]公共串

    [BZOJ2946][Poi2000]公共串

    试题描述

    给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
    任务:
    l        读入单词
    l        计算最长公共子串的长度
    l        输出结果

    输入

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

    输出

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

    输入示例

    3
    abcb
    bca
    acbc

    输出示例

    2

    数据规模及约定

    见“输入

    题解

    这道题

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 4010
    #define maxa 26
    
    char S[maxn];
    int len;
    
    int ToT, rt, last, to[maxn][maxa], par[maxn], Max[maxn];
    void extend(int x) {
    	int p = last, np = ++ToT; Max[np] = Max[p] + 1; last = np;
    	while(p && !to[p][x]) to[p][x] = np, p = par[p];
    	if(!p){ par[np] = rt; return ; }
    	int q = to[p][x];
    	if(Max[q] == Max[p] + 1){ par[np] = q; return ; }
    	int nq = ++ToT; Max[nq] = Max[p] + 1;
    	memcpy(to[nq], to[q], sizeof(to[q]));
    	par[nq] = par[q];
    	par[q] = par[np] = nq;
    	while(p && to[p][x] == q) to[p][x] = nq, p = par[p];
    	return ;
    }
    
    int sa[maxn], Ws[maxn], Ans[maxn], mn[maxn];
    
    int main() {
    	int n = read();
    	rt = last = ToT = 1;
    	scanf("%s", S); len = strlen(S);
    	for(int i = 0; i < len; i++) extend(S[i] - 'a');
    	
    	for(int i = 1; i <= ToT; i++) Ws[len-Max[i]]++;
    	for(int i = 1; i <= len; i++) Ws[i] += Ws[i-1];
    	for(int i = ToT; i; i--) sa[Ws[len-Max[i]]--] = i;
    	for(int i = 1; i <= ToT; i++) mn[i] = Max[i];
    	for(int k = 1; k < n; k++) {
    		scanf("%s", S);
    		int tmp = 0;
    		memset(Ans, 0, sizeof(Ans));
    		for(int i = 0, p = rt; S[i] != ''; i++) {
    			int x = S[i] - 'a';
    			if(to[p][x]) tmp++, p = to[p][x];
    			else {
    				while(p && !to[p][x]) p = par[p];
    				if(!p) p = 1, tmp = 0;
    				else tmp = Max[p] + 1, p = to[p][x];
    			}
    			Ans[p] = max(Ans[p], tmp);
    		}
    		for(int i = 1; i <= ToT; i++) {
    			int u = sa[i];
    			mn[u] = min(mn[u], Ans[u]);
    			if(Ans[u] && par[u]) Ans[par[u]] = Max[par[u]];
    		}
    	}
    	
    	int ans = 0;
    	for(int i = 1; i <= ToT; i++) ans = max(ans, mn[i]);
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    word 操作技巧
    有朝一日
    菜狗日记2021.7.10
    记一次JSON.toJSONString()踩坑
    菜狗日记2020.11.13
    菜狗日记2020.11.6
    菜狗日记2020.11.03
    菜狗日记2020.10.29
    菜狗日记2020.10.17
    菜狗日记2020.10.11
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6552337.html
Copyright © 2011-2022 走看看