标签:continue strong play copy turn 输入输出 描述 长度 自身
折叠的定义如下:
如果A = A’, B = B’,则AB = A’B’ 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B) = AAACBB,而2(3(A)C)2(B) = AAACAAACBB
给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。
仅一行,即字符串S,长度保证不超过100。
输出格式:仅一行,即最短的折叠长度。
NEERCYESYESYESNEERCYESYESYES
14
一个最短的折叠为:2(NEERC3(YES))
Solution:
本题考试时没搞出来。(话说老余$AK$了!,自己还是个蒟蒻‘!`~`!`)
就是一个区间$DP$,我这里用记忆化搜索来实现。
巧妙运用一下字符串$string$类型。定义状态$f[i][j]$表示区间$[i,j]$折叠后的最短字符串,那么当$l==r$时,显然$f[l][r]==s[l]$,搜索时枚举断点递归,找到使原串折叠后的长度最短的断点,然后枚举折叠的长度,这里用到了$stringstream$(字符串输入输出流)定义中间变量$op$,这样就可以简单的进行字符串的赋值,每一次$f[l][r]$赋为$f[l][r],op$中长度最短的一个(代码中的$op.tellp()$返回的是当前$put$流指针的位置(类似的还有$tellg$,返回$get$流指针的位置),可以理解为$op$的尾指针位置,即它的长度)。
这样写的好处是简洁而且能简单输出折叠后的字符串(一模一样的题,只是输出的是字符串,洛谷搜:$UVA1630\;Folding$,$STL$大法好!)。
此时先为不会$stringstream$的小伙伴们,安利一波(我测试的代码):
1 #include<iostream> 2 #include<sstream> //stringstream所需的头文件 3 using namespace std; 4 int main(){ 5 ios::sync_with_stdio(0); //取消流同步是可以用的,完全和string输入输出流无关 6 7 stringstream op; //定义string输入输出流,任意变量和string互转 8 string p; 9 char s[12]={"lalalavan"}; 10 op<<s; //将char类型的字符串赋值给op 11 op>>p; //将op输出到p中 12 cout<<op.str()<<endl<<p<<endl; //两种输出方式 13 14 op.str(""); 15 op.clear(); //对op清空必须两个都要用,可以自行尝试去掉一个,会出兮兮`~` 16 17 string num="23333"; 18 int n; 19 op<<num;op>>n; //将string类型转为int类型 20 cout<<n<<endl; //输出转换后的int类型 21 return 0; 22 }
本题代码:
1 #include<bits/stdc++.h> 2 #define il inline 3 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 4 #define Min(a,b) ((a)>(b)?(b):(a)) 5 #define INF 23333 6 using namespace std; 7 int n; 8 string s,f[105][105]; 9 il int check(int l,int r){ 10 int sl=r-l+1; 11 For(k,1,sl>>1){ 12 if(sl%k)continue; 13 bool f=1; 14 For(i,l,r-k){ 15 if(s[i]==s[i+k])continue; 16 f=0; 17 break; 18 } 19 if(f)return k; 20 } 21 return 0; 22 } 23 il string dfs(int l,int r){ 24 if(!f[l][r].empty())return f[l][r]; 25 if(l==r)return f[l][r]=s[l]; 26 int mink,ansl=INF; 27 For(i,l,r-1){ 28 int len=dfs(l,i).size()+dfs(i+1,r).size(); 29 if(len<ansl)mink=i,ansl=len; 30 } 31 f[l][r]+=dfs(l,mink),f[l][r]+=dfs(mink+1,r); 32 int k=check(l,r); 33 if(k){ 34 stringstream op; //定义输入输出流 35 op<<(r-l+1)/k<<"("<<dfs(l,l+k-1)<<")"; //将后面一大串依次赋给op 36 if(op.tellp()<f[l][r].size()) op>>f[l][r]; //比较f[l][r]和op取长度最小的 37 } 38 return f[l][r]; 39 } 40 int main(){ 41 cin>>s; 42 n=s.size(); 43 For(i,0,n-1) For(j,0,n-1)f[i][j].clear(); 44 cout<<dfs(0,n-1).size(); 45 return 0; 46 }
标签:continue strong play copy turn 输入输出 描述 长度 自身
原文地址:https://www.cnblogs.com/five20/p/9095505.html