Uva 1630 折叠串
Posted 树的种子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Uva 1630 折叠串相关的知识,希望对你有一定的参考价值。
题目链接:https://uva.onlinejudge.org/external/16/1630.pdf
题意:折叠串,给一个字符串,相同部分可以折叠,折叠可以嵌套。求最短长度的一种折叠方法。括号和数字的长度也要考虑进去。
刚看到这个题目,没有一点思路,还是大牛们厉害!
分析:一个串,可以转成两种形式,要么本身可以转成有重叠部分的串,要么分成两个部分,再转成有重叠部分的串。
本身是否是重叠串,利用kmp查,分成两个部分,遍历一遍所有情况,这样,dp顺序就出来了,最外层是每次查的长度,第二层就是,利用这个长度,从每一个点开始查起。状态描叙是d[i][j]从 i 到 j 的最短字符串。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 100 + 10; 5 6 string d[maxn][maxn]; 7 char s[maxn],t[maxn]; 8 9 10 11 int f[maxn]; 12 13 string ToString(int x) 14 { 15 string ans = ""; 16 while(x) 17 { 18 ans +=(char)(‘0‘+(x%10)); 19 x/=10; 20 } 21 reverse(ans.begin(),ans.end()); 22 return ans; 23 } 24 25 void getFail(char* s) 26 { 27 int len = strlen(s); 28 f[0] = f[1] = 0; 29 for(int i=1; i<len; i++) 30 { 31 int j = f[i]; 32 while(j&&s[i]!=s[j]) 33 j = f[j]; 34 f[i+1] = s[i]==s[j] ? j+1:0; 35 } 36 } 37 38 int main() 39 { 40 while(scanf("%s",s)!=EOF) 41 { 42 int len = strlen(s); 43 for(int i=0; i<len; i++) 44 d[i][i] = string("")+s[i]; 45 46 47 for(int l=2; l<=len; l++) 48 { 49 for(int i=0; i + l - 1 < len; i++) 50 { 51 int j = i + l - 1; 52 d[i][j] = ""; 53 for(int k=i; k<=j; k++) 54 { 55 d[i][j] +=s[k]; 56 t[k-i] = s[k]; 57 } 58 59 t[j-i+1] = 0; 60 getFail(t); 61 if(l%(l-f[l])==0) //自身是重复的 62 { 63 int cycle = l - f[l]; 64 string t = ""; 65 t = ToString(l/cycle); 66 t+=‘(‘; 67 t+=d[i][i+cycle-1]; 68 t+=‘)‘; 69 if(t.length()<d[i][j].length()) d[i][j] = t; 70 } 71 72 for(int k=i; k<j; k++) 73 { 74 if(d[i][k].length()+d[k+1][j].length()<d[i][j].length()) 75 { 76 d[i][j] = d[i][k] + d[k+1][j]; 77 } 78 } 79 } 80 } 81 cout<<d[0][len-1]<<endl; 82 } 83 return 0; 84 }
以上是关于Uva 1630 折叠串的主要内容,如果未能解决你的问题,请参考以下文章