3题校内垫底的屑
1002:
循环节找到以后直接双指针就行
考场上没有细算循环节长度,按照1e5算的,交上去自然是wa。正解的循环节最大长度在\(2^3\times3^2\times5\times7\times11=27720\times n\),然后还可能有横跨两个循环节的部分,因此长度还要再乘个二。
// Problem: Time-division Multiplexing
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=1031
// Memory Limit: 262 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 107, maxm = 27720 * 100 * 2;
#define ll long long
int n, m, k, tot, T;
char s[maxm+7];
int rd() {
int x;
scanf("%d", &x);
return x;
}
char a[107][14];
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int lcm = 1, len[107], cnt[300], flag, ans, flag0;
int main() {
T = rd();
while (T--) {
lcm = 1; ans = 999999999; tot = 0;
memset(cnt, 0, sizeof(cnt));
flag = 0;
n = rd();
for (int i = 1; i <= n; i++) {
scanf("%s", a[i]);
k = strlen(a[i]);
for (int j = 0; j < k; j++) {
if (cnt[a[i][j]]==0) {
flag++;
}
cnt[a[i][j]]++;
}
len[i] = k;
lcm = k * lcm / gcd(k, lcm);
}
lcm = lcm*2*n;
for (int cur = 0; tot < lcm; cur++) {
for (int i = 1; i <= n; i++) {
s[tot++] = a[i][cur%len[i]];
}
}
int l = 0, r = -1;
flag0 = flag;
flag = 0;
memset(cnt, 0, sizeof(cnt));
while (r < lcm) {
while (flag < flag0 && r < lcm) {
r++;
if (r == lcm) break;
if (cnt[s[r]] == 0) {
flag++;
}
cnt[s[r]]++;
}
if (r == lcm) break;
while (flag == flag0 && l < r) {
cnt[s[l]]--;
if (cnt[s[l]] == 0) {
flag--;
}
l++;
if (flag == flag0)
ans = min(ans, r-l+1);
}
if (flag == flag0 && l <= r)
ans = min(ans, r-l+1);
}
//printf("s == %s\n", s);
printf("%d\n", ans);
}
return 0;
}
1012:
wa傻了,待补。