HDU 1274 展开字符串
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1274
不太懂,,先发表别人的。。。慢慢研究。。。。
算法:
用了最直接,最暴力的方法。一层层展开。从右到左,遇到(或是数字就展开。
一开始想了很多,想得很复杂,但都没办法想下去。于是,就用最简单的方法,直接AC了。原以为是超时的。
幸好数据不是很大。用了两个字符数组,一个用于存重复内容。一个存后辍
具体做法。
统一性。
1。没括号的,数字+字母,字母这两种类型。当成数字+(字母),(字母)类型。重复内容,直接是单个字母。
2。没数字的,字母,(字符串),当成1+字母,1+(字符串)类型。重复次数是1次。
这样就把上面的所有情况统一化了。之后只要一个函数就可以完成每一次的重复内容的。
下面是AC代码:
1 #include<stdio.h> 2 #include<string.h> 3 4 5 char str[3000001]; 6 char ans[1000000]; 7 char help[100000]; 8 int n,len; 9 10 void solve_other(int sum,char help[],char ans[],int k) 11 { 12 int p,q; 13 for(p=1;p<=sum;p++) 14 { 15 for(q=0;help[q]!=0;q++) 16 { 17 str[k++]=help[q]; 18 } 19 } 20 for(q=0;ans[q]!=0;q++) 21 { 22 str[k++]=ans[q]; 23 } 24 len=k; 25 } 26 27 void solve() 28 { 29 int i,j; 30 int p,q,k; 31 int sum; 32 for(i=n-1;i>=0;i--) 33 { 34 if(str[i]=='(') 35 { 36 for(j=i+1;;j++) 37 { 38 if(str[j]==')') 39 { 40 help[j-i-1]=0; 41 break; 42 } 43 help[j-i-1]=str[j]; 44 } 45 sum=0; 46 p=1; 47 while(i-1>=0&&str[i-1]>='0'&&str[i-1]<='9') 48 { 49 sum=(str[i-1]-'0')*p+sum; 50 p=p*10; 51 i--; 52 } 53 if(sum==0) sum=1; 54 for(q=j+1;q<len;q++) 55 { 56 ans[q-j-1]=str[q]; 57 } 58 ans[q-j-1]=0; 59 k=i; 60 solve_other(sum,help,ans,k); 61 62 } 63 else if(str[i]>='0'&&str[i]<='9') 64 { 65 sum=0; 66 p=1; 67 j=i+1; 68 while(i>=0&&str[i]>='0'&&str[i]<='9') 69 { 70 sum=(str[i]-'0')*p+sum; 71 p=p*10; 72 i--; 73 } 74 i++; 75 if(sum==0) sum=1; 76 if(j<n) 77 { 78 help[0]=str[j]; 79 help[1]=0; 80 for(p=j+1;p<len;p++) 81 { 82 ans[p-j-1]=str[p]; 83 } 84 ans[p-j-1]=0; 85 solve_other(sum,help,ans,i); 86 } 87 } 88 } 89 str[len]=0; 90 } 91 92 int main() 93 { 94 int k; 95 96 scanf("%d",&k); 97 while(k--) 98 { 99 scanf("%s",str); 100 n=strlen(str); 101 len=n; 102 solve(); 103 printf("%s/n",str); 104 105 } 106 return 0; 107 }
法二:
1 #include "stdio.h" 2 #include "string.h" 3 4 char sss[260]; 5 6 int kh[260]; //括号匹配 7 8 int digit(char c){ 9 return c >= '0' && c <= '9'; 10 } 11 12 void print(int st, int ed){ 13 int i, j; 14 15 for(i=st; i<=ed; ){ 16 17 if(digit(sss[i])){ 18 if(sss[i+1] == '('){ //3(abc...) 或者 1(abc...) 19 for(j=0; j<sss[i]-'0'; j++) 20 print(i+2, kh[i+1]-1); 21 i = kh[i+1] + 1; 22 }else{ //3abc... 23 for(j=0; j<sss[i]-'0'; j++) 24 printf("%c", sss[i+1]); 25 i += 2; 26 } 27 28 }else{ 29 if(sss[i] == '('){ //(abc...) 30 print(i+1, kh[i]-1); 31 i = kh[i]+1; 32 }else //abc... 33 printf("%c", sss[i++]); 34 } 35 36 } 37 } 38 39 void main(){ 40 int n; 41 int i; 42 int stack[251]; 43 int top; 44 45 freopen("in.txt", "r", stdin); 46 47 scanf("%d", &n); 48 while(n--){ 49 getchar(); 50 scanf("%s", sss); 51 top = 0; 52 for(i=strlen(sss)-1; i>=0; i--){ 53 if(sss[i] == ')') 54 stack[top++] = i; 55 if(sss[i] == '('){ 56 top--; 57 kh[i] = stack[top]; 58 } 59 } 60 61 print(0, strlen(sss)-1); 62 printf("\n"); 63 } 64 }
法三:
1 #include <iostream> 2 using namespace std; 3 char input[250005]; 4 char str[250005]; 5 int main() 6 { 7 int cas; 8 #ifndef ONLINE_JUDGE 9 freopen("in.txt", "r", stdin); 10 #endif 11 scanf("%d", &cas); 12 while (cas--) 13 { 14 scanf("%s", input); 15 int len; 16 while (1) 17 { 18 int flag = 0; 19 int c = 0; 20 int i, j, k; 21 len = strlen(input); 22 for (i = 0; i < len; ++i) 23 { 24 if (input[i] >= 'a' && input[i] <= 'z') 25 { 26 str[c++] = input[i]; 27 } 28 else if (input[i] >= '0' && input[i] <= '9') 29 { 30 int cnt = 0; 31 while (input[i] >= '0' && input[i] <= '9') 32 { 33 cnt *= 10; 34 cnt += input[i] - '0'; 35 ++i; 36 } 37 if (input[i] != '(') 38 { 39 while (cnt--) 40 { 41 str[c++] = input[i]; 42 } 43 } 44 else 45 { 46 int t = 1; 47 int temp = i + 1; 48 while (t != 0) { 49 if (input[temp] == '(') 50 { 51 ++t; 52 } 53 if (input[temp] == ')') 54 { 55 --t; 56 } 57 ++temp; 58 } 59 for (j = 0; j < cnt; ++j) 60 { 61 for (k = i + 1; k < temp - 1; ++k) 62 { 63 str[c++] = input[k]; 64 if (input[k] == '(' || input[k] == ')' || (input[k] >= '0' && input[k] <= '9')) 65 { 66 flag = 1; 67 } 68 } 69 } 70 i = temp - 1; 71 } 72 } 73 } 74 str[c] = 0; 75 memcpy(input, str, sizeof(str)); 76 if (flag == 0) 77 { 78 break; 79 } 80 } 81 cout << str << endl; 82 } 83 return 0; 84 }
法四:
//一个很不错的递归题,我主要的过程就如一般的表达式求解,遇到左括号进入下层递归,
//否则一直按每个字母前面的数字决定其输出的次数,括号也是如此,而递归结束的标志
//则是遇到 右括号或者到字符串的结尾,注意每次递归结束需要返回下次遍历的序号
1 #include<stdio.h> 2 #include<ctype.h> 3 #include<string.h> 4 char s[260]; 5 int dfs(int ith) 6 { 7 int k,e; 8 char c; 9 for(c=s[ith++];ith<strlen(s)&&c!=')';c=s[ith++])//递归结束的条件是字符串结束或遇到右括号 10 { 11 for(k=0;isdigit(c);c=s[ith++]) 12 k=k*10+c-'0'; 13 if(!k) k=1; 14 if(c=='('){ 15 while(k--) 16 e=dfs(ith); 17 ith=e;//重置ith的值,到下层递归结束的位置 18 } 19 else{ 20 while(k--) 21 putchar(c); 22 } 23 } 24 if(c==')') return ith;//返回本次读到结尾的位置 25 } 26 int main() 27 { 28 int n; 29 scanf("%d",&n); 30 while(n--) 31 { 32 scanf("%s",s); 33 dfs(0);//进入递归 34 printf("\n"); 35 } 36 return 0; 37 }