#include<bits/stdc++.h>
using namespace std;
#define pos(x,y) st[x%y][x/y%len[x%y]]-'a'
//x%y是求 是第几个串,x/y求 是补齐后的串里 第几个字符,%len[x%y]是求原串里是第几个字符
//pos(x,y)求第x个加入的字符,转为int二进制在哪位。(主要是为了区分26个字母)
typedef long long ll;
const int maxn=105,maxm=15;
int n,len[maxn],cnt[27];
char st[maxn][maxm];
int main(){
int t,g,ml,f,f2;
//min公倍数,字符串的最大长度 ,需要出现的所有字符,
cin>>t;
while(t--){
g=1,ml=0,f=f2=0;
memset(cnt,0,sizeof(cnt));
scanf("%d",&n);
//小细节:按0~n-1存,%n才是正常的。所以下面p2要从-1开始
for(int i=0;i<n;i++){
scanf("%s",st[i]);
len[i]=strlen(st[i]);
for(int j=0;j<len[i];j++)
f|=1<<st[i][j]-'a';
//先1左移()位 ,在赋值或给f。即将st[i][j]-'a'位变为1
//f记录每组数据 的所有字符串 共出现哪些字母
if(len[i]>ml) ml=len[i];
g=g*len[i]/__gcd(g,len[i]);
}
int p1=0,p2=-1,tot=(g+ml)*n;
int ans=tot;
while(p2<tot){
//小while里p2在++,所以也要判断下p2<tot
//里面2个while并列表示双指针p1p2的移动方式
while(f2!=f&&p2<tot){
++p2;
++cnt[pos(p2,n)];//存26个字母各出现多少次
f2|=1<<pos(p2,n);
}
//用while不用if,因为里面f2在变。有可能++p1为起点的 也满足
while(f2==f){
//ans求各个起点的 最短的
ans=min(ans,p2-p1+1);
//对于以p1为起点的,找到满足的就是最短的,所有p1的不用再考虑了,可以看++p1,
--cnt[pos(p1,n)];//所有p1这个位置的字母也去掉
if(cnt[pos(p1,n)]==0)
f2&=~(1<<pos(p1,n));
//若这个字母次数为0。按位与上0,即除去这位(即起始位这个字母)
++p1;
}
}
printf("%d\n",ans);
}
}
hdu7101滑动窗口
猜你喜欢
转载自blog.csdn.net/weixin_50904510/article/details/120064500
今日推荐
周排行