• [BZOJ4698][Sdoi2008]Sandy的卡片


    [BZOJ4698][Sdoi2008]Sandy的卡片

    试题描述

    Sandy和Sue的热衷于收集干脆面中的卡片。然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型。每一张卡片都由一些数字进行标记,第i张卡片的序列长度为Mi,要想兑换人物模型,首先必须要集够N张卡片,对于这N张卡片,如果他们都有一个相同的子串长度为k,则可以兑换一个等级为k的人物模型。相同的定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串。Sandy的卡片数远远小于要求的N,于是Sue决定在Sandy的生日将自己的卡片送给Sandy,在Sue的帮助下,Sandy终于集够了N张卡片,但是,Sandy并不清楚他可以兑换到哪个等级的人物模型,现在,请你帮助Sandy和Sue,看看他们最高能够得到哪个等级的人物模型。

    输入

    第一行为一个数N,表示可以兑换人物模型最少需要的卡片数,即Sandy现在有的卡片数
    第i+1行到第i+N行每行第一个数为第i张卡片序列的长度Mi,之后j+1到j+Mi个数,用空格分隔,分别表示序列中
    的第j个数
    N<=1000,2<=Mi<=101

    输出

    一个数k,表示可以获得的最高等级。

    输入示例

    2
    2 1 2
    3 4 5 9

    输出示例

    2

    数据规模及约定

    见“输入

    题解

    首先把所有串差分一下;再把第一个串的每个后缀分别当成模板串依次对第 2~n 个串跑 KMP,找到能够匹配所有第 2~n 个串的最长子串。

    #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 1010
    #define maxl 110
    
    int n, len[maxn], S[maxn][maxl], Fail[maxl];
    
    int main() {
    	n = read();
    	for(int i = 1; i <= n; i++) {
    		len[i] = read();
    		for(int j = 1; j <= len[i]; j++) S[i][j] = read();
    		len[i]--;
    		for(int j = 1; j <= len[i]; j++) S[i][j] = S[i][j+1] - S[i][j];
    	}
    	/*for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= len[i]; j++) printf("%d%c", S[i][j], j < len[i] ? ' ' : '
    '); // */
    	
    	int ans = 0;
    	for(int st = 1; st <= len[1] - ans; st++) {
    		int nl = len[1] - st + 1;
    		for(int i = 2; i <= nl + 1; i++) {
    			int j = Fail[i-1];
    			while(j > 1 && S[1][j+st-1] != S[1][i+st-2]) j = Fail[j];
    			Fail[i] = S[1][j+st-1] == S[1][i+st-2] ? j + 1 : 1;
    		}
    		int p, k = len[1];
    		for(int x = 2; x <= n; x++) {
    			p = 1; int tmp = 0;
    			for(int i = 1; i <= len[x]; i++) {
    				while(p > 1 && S[1][p+st-1] != S[x][i]) p = Fail[p];
    				p = S[1][p+st-1] == S[x][i] ? p + 1 : 1;
    				tmp = max(tmp, p - 1);
    			}
    			k = min(k, tmp);
    			if(k <= ans) break;
    		}
    		ans = max(ans, k);
    	}
    	
    	printf("%d
    ", ans + 1);
    	
    	return 0;
    }
    
  • 相关阅读:
    刷题笔记
    布隆过滤器
    单例模式,堆,BST,AVL树,红黑树
    B树、B-树、B+树、B*树【转】,mysql索引
    数据结构与算法80道
    海量数据处理【转】
    volcanol的工控博客
    volcanol的工控博客
    volcanol的工控博客
    volcanol的工控博客
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6483023.html
Copyright © 2020-2023  润新知