HDU7101 - Time-division Multiplexing
题意
给定 n n n个字符串 s 1 , s 2 , . . . , s n s_1,s_2,...,s_n s1,s2,...,sn,按照一定规则将字符串输出到 a n s ans ans中。
一开始所有字符串都按照顺序将第 1 1 1个字符(即 s [ i ] [ p o s i ] , p o s i = 0 s[i][pos_i],pos_i=0 s[i][posi],posi=0)输出到 a n s ans ans中:
然后 ∀ i , p o s i = ( p o s i + 1 ) m o d l e n ( s [ i ] ) \forall i,pos_i = (pos_i+1)\ mod\ len(s[i]) ∀i,posi=(posi+1) mod len(s[i]),将所有字符串的 s [ i ] [ p o s i ] s[i][pos_i] s[i][posi]按顺序输出到 a n s ans ans,重复这个操作不停止,最后会重复出现同一个字符串 s t r str str(即 a n s = s t r + s t r + . . . + s t r ans=str+str+...+str ans=str+str+...+str)。
动图好麻烦
思路
这道题题意比较难懂,但是题目并不难。
先将输出串中的重复串 s t r str str提取出来:
可以记录一个数组 p o s i pos_i posi,除了一开始的情况,直到 ∀ i , p o s i = = 0 \forall i, pos_i==0 ∀i,posi==0时就停止记录,这时候的输出串就是重复串 s t r str str。
然后去找最小范围的 [ l , r ] [l,r] [l,r]使得包含 s t r str str中所有不同的字符,这是一个经典的问题了(双指针)。
!!
有一点需要注意一下,取得的最小范围不一定在
s
t
r
str
str能,可能在
s
t
r
+
s
t
r
str+str
str+str上,所以需要将
s
t
r
=
s
t
r
+
s
t
r
str=str+str
str=str+str.
AC的代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
char s[N][20];
int pos[N], n;
bool k = true;
bool check() {
if (k) {
k = false;
return false;
}
for (int i = 1; i <= n; i++)
if (pos[i] != 0) return false;
return true;
}
int solve(string str) {
int res = str.size();
int E[30];
for (int i = 0; i < 26; i++) E[i] = 0;
// =========================================
int all = 0; // 记录有多少个不同的字符
for (int i = 0; i < str.size(); i++) {
int tmp = str[i] - 'a';
if (E[tmp] == 0) all++;
E[tmp]++;
}
for (int i = 0; i < 26; i++) E[i] = 0;
// =========================================
int l = 0, r = 0; // 双指针
int cnt = 0;
while (l < str.size() && r < str.size()) {
while (cnt < all && r < str.size()) { // 直到所有不同字符都都包含时停下
int tmp = str[r] - 'a';
if (E[tmp] == 0) cnt++;
E[tmp]++;
r++;
}
bool key = false;
if (cnt >= all) // 只有l-r能取到所有不同字符时才记录答案
key = true;
else
break;
while (l < r && cnt >= all) { // 恰好不满足
int tmp = str[l] - 'a';
E[tmp]--;
if (E[tmp] == 0) cnt--;
l++;
}
if (key) res = min(res, (r - l + 1));
}
return res;
}
int main() {
int t;
cin >> t;
while (t--) {
cin >> n;
string str = "";
for (int i = 1; i <= n; i++) cin >> s[i];
memset(pos, 0, sizeof pos);
k = true;
while (!check()) { // 寻找重复出现的"输出串"
for (int i = 1; i <= n; i++) {
str += s[i][pos[i]];
pos[i] = (pos[i] + 1) % strlen(s[i]);
}
}
str += str;
cout << solve(str) << endl;
}
return 0;
}