题解报告——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+1+Mi个数,用空格分隔,分别表示序列中的第j个数
输出格式:
一个数k,表示可以获得的最高等级。
输入输出样例
输入样例#1:
2 2 1 2 3 4 5 9
输出样例#1:
2
说明
数据范围:
30%的数据保证n<=50
100%的数据保证n<=1000,M<=1000,2<=Mi<=101
【思路分析】
我们看到了这道题相同的定义为字串每个字符加一定的值相同即可,所以我们只需要找到相邻关系相同即可,这里我们就只需要相邻之差相同即可,那我们将维护原序列改为维护差值序列,然后只需要hash判断出现次数即可。
【代码实现】
1 #include<cstdio> 2 #include<cstring> 3 #include<cctype> 4 #include<algorithm> 5 #include<queue> 6 #define mp make_pair 7 using namespace std; 8 const int N=1e3+5,M=105; 9 const int mod=517619,base=233; 10 void read(int &v) 11 { 12 int f;char ch; 13 while(!isdigit(ch=getchar())&&ch!='-'); ch=='-'?(v=0,f=-1):(v=ch-'0',f=1); 14 while(isdigit(ch=getchar())) v=v*10+ch-'0';v=v*f; 15 } 16 int st[N][M],n,m,time[mod],ans; 17 bool hash[mod],vis[mod]; 18 int main() 19 { 20 read(n); 21 for(int i=1;i<=n;i++) 22 { 23 memset(vis,0,sizeof(vis)); 24 read(m); 25 for(int j=1;j<=m;j++) read(st[i][j]); 26 for(int j=1;j<m;j++) st[i][j]=st[i][j+1]-st[i][j]+9; 27 //for(int j=1;j<m;j++) printf("[%d] ",st[i][j]);printf("\n"); 28 int cnt=0; 29 for(int l=1;l<m;l++) 30 { 31 int now=0; 32 for(int r=l;r<m;r++) 33 { 34 now=(1ll*now*base%mod+st[i][r])%mod; 35 if(i>1) {if(hash[now]&&!vis[now]) vis[now]=1,time[now]++;} 36 else hash[now]=1,time[now]=1; 37 if(i==n&&time[now]>=n) ans=max(ans,r-l+1); 38 } 39 } 40 } 41 printf("%d",ans+1); 42 return 0; 43 }