题目 | We Love Strings
2023牛客暑期多校训练营7
I - We Love Strings
https://ac.nowcoder.com/acm/contest/57361/I
题意
给定 0,1,?
的正则串,?
可以匹配一个 0
或 1
,问有多少个
题解
这道题的突破口不在题目本身,而在数据范围上。正则串个数最多
暴力法
如果 0/1 串长度为
暴力法时间复杂度为
容斥原理法
对于一个正则串
接下来的要解决的问题就是怎么统计每种交情况的集合数量了。
对于
- 初始化一个串
为 对于每个
,逐位考察:- 如果
, :令 . - 如果
, :不操作 - 如果
, :发生矛盾!直接退出算法,匹配数为 .
- 如果
- 统计串
内的 数目为 - 能同时匹配
中所有正则串的 0/1 串数目为:
最后,对于元素个数为奇数的子集,加上它们的答案,对于元素个数为偶数的子集,减去它们的答案,便是最终答案了。
容斥原理法时间复杂度为
两种方法结合
可以发现暴力法时间复杂度关于
- 当
时,数据范围保证 ,选择暴力法. - 当
时,数据范围保证 ,选择容斥原理法.
(时间复杂度算出来
代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
constexpr int MOD = 998244353;
// 暴力 Brute Force
int brute_force(vector<string> &arr)
{
int len = arr.front().length();
int siz = arr.size();
int res = 0;
for (int i = 0; i < (1 << len); i++)
{
for (int j = 0; j < siz; j++)
{
bool flag = true;
for (int k = 0; k < len; k++)
{
if (arr[j][k] == '?')
continue;
if (arr[j][k] != (i >> k & 1) + '0')
{
flag = false;
break;
}
}
if (flag)
{
res++;
break;
}
}
}
return res;
}
// 容斥原理 Include-Exclude Principle
int inc_exc(vector<string> &arr)
{
int len = arr.front().length();
int siz = arr.size();
int res = 0;
for (int i = 1; i < (1 << siz); i++)
{
bool flag = true;
string match(len, '?');
for (int j = 0; flag && j < siz; j++)
{
if ((i >> j & 1) == 0)
continue;
for (int k = 0; k < len; k++)
{
if (match[k] == '0' && arr[j][k] == '1' ||
match[k] == '1' && arr[j][k] == '0')
{
flag = false;
break;
}
if (match[k] == '?')
match[k] = arr[j][k];
}
}
if (!flag)
continue;
int tmp = 1;
for (int j = 0; j < len; j++)
if (match[j] == '?')
tmp = (tmp * 2) % MOD;
bool op = __builtin_popcount(i) & 1; // odd+ even-
if (op)
res = (res + tmp) % MOD;
else
res = (res - tmp + MOD) % MOD;
}
return res;
}
void solve()
{
int n;
cin >> n;
map<int, vector<string>> mp;
for (int i = 1; i <= n; i++)
{
string s;
cin >> s;
mp[s.length()].emplace_back(s);
}
int ans = 0;
for (auto &[len, arr] : mp)
{
if (len <= 20)
ans = (ans + brute_force(arr)) % MOD;
else
ans = (ans + inc_exc(arr)) % MOD;
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi