lg2400 秘密文件

tag:区间dp


AT3859 [AGC020E] Encoding Subsets一模一样。。(这个黑的还好写一点,因为是计数)

\(f(s)\)\(s\) 的答案,\(g(s)\) 为将 \(s\) 表示成k(s') 的答案。

\(f\) 时枚举一个前缀,用 \(g(s_{[0,i]})+f(s_{[i+1,len-1]})\) 更新答案。

\(g\) 时暴力枚举循环节,暴力判断。


这题善用string的函数吧,会好写很多

#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
	char ch; bool flag=false;
	while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
	for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
	if(flag)n=-n;
}

map<string,string>f;
map<string,string>g;

inline string F(string);
inline string G(string);

inline void update(string &a, string b){
	if(b.size() < a.size()) a = b;
	else if(b.size()==a.size() and a<b) a = b;
}

inline string itos(int val){
	string res="";
	while(val) res += val%10+'0', val /= 10;
	reverse(res.begin(),res.end());
	return res;
}

vector<int>p[105];

int main(){
	for(int i=1; i<=100; i++) for(int j=i+i; j<=100; j+=i) p[j].push_back(i);
	string s; cin>>s;
	cout<<F(s)<<'\n';
	return 0;
}

inline string F(string s){
	if(f.count(s)) return f[s];
	string res = G(s); int n = s.size();
	for(int i=1; i<n; i++) update(res,G(s.substr(0,i))+F(s.substr(i,n-i)));
	return f[s]=res;
}

inline string G(string s){
	if(g.count(s)) return g[s];
//	cout<<"G "<<s<<'\n';
	string res = s; int n = s.size();
	for(int i=0, tp=p[n].size(); i<tp; i++){
		int len=p[n][i];
		char rep=true;
		for(int j=len; j<n; j++) if(s[j]!=s[j-len]){rep=false; break;}
		if(rep==false) continue;
		update(res,itos(n/len)+"("+F(s.substr(0,len))+")");
	}
	return g[s]=res;
}
posted @ 2021-06-25 09:02  oisdoaiu  阅读(39)  评论(0编辑  收藏  举报