题目传送门
题目描述
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+1+Mi个数,用空格分隔,分别表示序列中的第j个数
输出格式:
一个数k,表示可以获得的最高等级。
输入输出样例
说明
数据范围:
30%的数据保证n<=50
100%的数据保证n<=1000,M<=1000,2<=Mi<=101
题解:
先对每个原串差分,再把n个差分后的串连在一起,中间用未出现过的字符隔开。求出height数组后进行二分答案,查看是否有满足条件的[l,r]使得区间内出现了n个卡组且height都大于等于二分出的x。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define LL long long 6 #define RI register int 7 using namespace std; 8 const int INF = 0x7ffffff ; 9 const int N = 1e6 + 1010 ; 10 11 inline int read() { 12 int k = 0 , f = 1 ; char c = getchar() ; 13 for( ; !isdigit(c) ; c = getchar()) 14 if(c == '-') f = -1 ; 15 for( ; isdigit(c) ; c = getchar()) 16 k = k*10 + c-'0' ; 17 return k*f ; 18 } 19 int n, nn, k, p, q = 1, tot = 0, res = 0 ; int a[N], bl[N], sa[2][N], rk[2][N], h[N], v[N] ; 20 21 inline void mul(int *sa,int *rk,int *SA,int *RK) { 22 for(int i=1;i<=n;i++) v[rk[sa[i]]] = i ; 23 for(int i=n;i;i--) if(sa[i] > k) SA[v[rk[sa[i]-k]]--] = sa[i]-k ; 24 for(int i=n-k+1;i<=n;i++) SA[v[rk[i]]--] = i ; 25 for(int i=1;i<=n;i++) RK[SA[i]] = RK[SA[i-1]] + (rk[SA[i]] != rk[SA[i-1]] || rk[SA[i]+k] != rk[SA[i-1]+k]) ; 26 } 27 inline void presa() { 28 for(int i=1;i<=n;i++) v[a[i]]++ ; 29 for(int i=1;i<=222;i++) v[i] += v[i-1] ; 30 for(int i=1;i<=n;i++) sa[p][v[a[i]]--] = i ; 31 for(int i=1;i<=n;i++) rk[p][sa[p][i]] = rk[p][sa[p][i-1]] + (a[sa[p][i]] != a[sa[p][i-1]]) ; 32 for(k=1;k<n;k<<=1,swap(p,q)) { 33 mul(sa[p],rk[p],sa[q],rk[q]) ; 34 if(rk[q][sa[q][n]] == n) { 35 swap(p,q) ; break ; 36 } 37 } 38 for(int i=1,k=0;i<=n;i++) { 39 int j = sa[p][rk[p][i]-1] ; 40 while(a[i+k] == a[j+k]) k++ ; 41 h[rk[p][i]] = k ; if(k) k-- ; 42 } 43 } 44 45 int vv[1010] ; 46 inline void add(int x) { 47 if(!x) return ; 48 if(!vv[x]) res ++ ; 49 vv[x]++ ; 50 } 51 inline void del(int x) { 52 if(!x) return ; 53 vv[x]-- ; 54 if(!vv[x]) res -- ; 55 } 56 inline bool check(int x) { 57 memset(vv,0,sizeof(vv)) ; 58 int pre = 0 ; res = 0 ; 59 for(int i=1;i<=n;i++) { 60 if(h[i] < x) { 61 if(res == nn) return 1 ; 62 for(int j=pre+1;j<i;j++) del(bl[sa[p][j]]), del(bl[sa[p][j-1]]) ; 63 pre = i ; 64 } 65 else add(bl[sa[p][i]]), add(bl[sa[p][i-1]]) ; 66 } 67 if(res == nn) return 1 ; // 刚刚那个提交少了这一行,其实是有漏洞的qaq 68 return 0 ; 69 } 70 71 int main() { 72 n = read() ; 73 for(int i=1;i<=n;i++) { 74 int mm = read() ; int now, pre = read() ; 75 for(int j=1;j<mm;j++) now = read(), a[++tot] = now-pre+102, pre = now, bl[tot] = i ; 76 if(i < n) a[++tot] = 222 ; 77 } 78 nn = n ; n = tot ; presa() ; 79 int L = 0, R = n, ans = 0 ; 80 while(L < R) { 81 int mid = (L+R)>>1 ; 82 if(check(mid)) ans = max(ans,mid), L = mid+1 ; 83 else R = mid ; 84 } 85 /* 86 for(int i=1;i<=n;i++) printf("%d ",a[i]) ; printf(" ") ; 87 for(int i=1;i<=n;i++) printf("%d ",h[rk[p][i]]) ; printf(" ") ; 88 */ 89 printf("%d",ans+1) ; 90 return 0 ; 91 }
又一次把v[]开小了...不会再有下一次了qaq