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;
}