hdu 7101 Time-division Multiplexing
题意:
- n n n 个字符串,按顺序循环取字符产生一个新的无限长的字符串,具体看 H i n t Hint Hint
- 要在新的字符串里找到最短的子串,使子串中出现所有字符,求最短的子串长度
分析:
-
那肯定不会是无限长的字符串,循环取,考虑字符串的循环节
单个串 l e n < = 12 len<=12 len<=12 , l c m lcm lcm 最大为 2 ∗ 3 ∗ 2 ∗ 5 ∗ 7 ∗ 2 ∗ 3 ∗ 11 = 27720 2*3 ∗ 2 ∗ 5 ∗ 7 ∗ 2 ∗ 3 ∗ 11 = 27720 2∗3∗2∗5∗7∗2∗3∗11=27720 ,所以一个循环节最长为 27720 ∗ n 27720 ∗ n 27720∗n ,不同的字符最多散落在两个循环节内,故总长度应该是 27720 ∗ n ∗ 2 27720 ∗ n ∗ 2 27720∗n∗2 ,用双指针算法求解即可
#include <bits/stdc++.h>
using namespace std;
char s[105][15];
int len[105], cnt[155];
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
cin>>T;
while(T--)
{
memset(cnt,0,sizeof(cnt));
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
len[i]=strlen(s[i]);
for(int j=0;j<len[i];j++) if(!cnt[s[i][j]]) cnt[s[i][j]]=1;
}
int d=0;
for(int i=0;i<128;i++) if(cnt[i]) d++;
string sr;
for(int i=0;i<27720*2;i++)
{
for(int j=1;j<=n;j++)
{
sr.push_back(s[j][i%len[j]]);
}
}
int j=0, tot=0, ans=1e9;
memset(cnt,0,sizeof(cnt));
for(int i=0;i<sr.size();i++)
{
char c=sr[i];
if(!cnt[c]) tot++;
cnt[c]++;
while(cnt[sr[j]]>1) // 双指针
{
cnt[sr[j]]--; j++;
}
if(tot==d) ans=min(ans,i-j+1);
}
cout<<ans<<endl;
}
return 0;
}