[BZOJ4698][Sdoi2008]Sandy的卡片
试题描述
输入
输出
一个数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] ? ‘ ‘ : ‘\n‘); // */ 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\n", ans + 1); return 0; }
原文:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/6483023.html