其他分享
首页 > 其他分享> > AT3859 [AGC020E] Encoding Subsets

AT3859 [AGC020E] Encoding Subsets

作者:互联网

有一道题 也是字符串的压缩,但是要求的是压缩后的最短长度,然后做法是区间 \(\tt DP\)。故考虑区间 \(\tt DP\)(应该比较显然看出)。

我们先把问题弱化:去掉“包含”的条件,对单个字符串求答案。

考虑如刚刚那题,记录 \(f_{l,r}\) 代表一个区间的答案。

但是这一个不够(我考场上在这里挣扎了许久),还要用 \(g_{l,r}\) 代表 不是由多个压缩合并而成的压缩的答案

转移不难。

考虑原问题。

我们不妨用一个字符串 \(S\) 代替原先的状态 \(\{l,r\}\),代表 \(S\) 的答案。

  1. 找到每个 \(T\) 需要覆盖上的字符串 \(T^{\prime}\) 的对应位。
  2. 如果全部都是 \(1\),那这一位就可以取到 \(1\)(如果有一位是 \(0\),根据“包含”的规则,无法将其改变成 \(1\)。)
  3. 一定可以取到 \(0\)(如果有一位是 \(1\),根据“包含”的规则,可以将其改变成 \(1\)。)

对于状态的存储,考虑记忆化搜索,然后 unordered_map<string,int> 解决。

#import<iostream>
#import<unordered_map>
using namespace std;

using ll = long long;
const ll mod = 998244353;

string st;
unordered_map<string,int> f,g;

ll F(string s);
ll G(string s);

ll F(string s){
	if(f.find(s) != f.end()) return f[s];
	int sum = 0,len = s.length();
	for(int i = 1;i <= len;++i)
		(sum += G(s.substr(0,i)) * F(s.substr(i,len - i + 1)) % mod) %= mod;
	return f[s] = sum;
}

ll G(string s){
	if(g.find(s) != g.end()) return g[s];
	int sum = 0,len = s.length();
	for(int i = 1;i < len;++i) if(len % i == 0){
		string str = "";
		for(int p = 0;p < i;++p){
			bool f = 1;
			for(int q = p;q < len;q += i)
				f &= (s[q] - '0');
			str += f ? '1' : '0';
		}
		(sum += F(str)) %= mod;
	}
	return g[s] = sum;
}

void init(){ f[""] = g[""] = g["0"] = 1; g["1"] = 2; }

int main(){
	cin >> st;
	init();
	cout << F(st) << endl;
	return 0;
}

标签:string,Subsets,Encoding,ll,AT3859,枚举,循环,字符串,sum
来源: https://www.cnblogs.com/zeno6174/p/AT3859.html