您的位置:首页 > 其它

给定任意字符串,计算一共能组合成多少个单词bing

2016-07-29 00:00 309 查看
CSDN编程挑战里的题目

例如有一个字符串"iinbinbing",截取不同位置的字符‘b’、‘i’、‘n’、‘g’组合成单词"bing"。
若从1开始计数的话,则‘b’ ‘i’ ‘n’ ‘g’这4个字母出现的位置分别为(4,5,6,10) (4,5,9,10),
(4,8,9,10)和(7,8,9,10),故总共可以组合成4个单词”bing“。
问题是:现给定任意字符串,只包含小写‘b’ ‘i’ ‘n’ ‘g’这4种字母,请问一共能组合成多少个单词bing?

字符串长度不超过10000,由于结果可能比较大,请输出对10^9 + 7取余数之后的结果。

这个问题写个四重循环就可以.只是效率方面还有待优化.

第一版代码:

1 #include <stdio.h>
2 #include <iostream>
3 #include <string>
4
5 #include <cstring>
6 #include <cstdio>
7
8 #define BING_MAX 1000000007
9
10 int Bing(const char* szBing)  11 {  12     if (!szBing || !szBing[0])  13  {  14         return 0;  15  }  16
17     int len = (int)strlen(szBing);  18     int* listPosB = (int*)malloc(len*sizeof(int));  19     int* listPosI = (int*)malloc(len*sizeof(int));  20     int* listPosN = (int*)malloc(len*sizeof(int));  21     int* listPosG = (int*)malloc(len*sizeof(int));  22     memset(listPosB, 0, len*sizeof(int));  23     memset(listPosI, 0, len*sizeof(int));  24     memset(listPosN, 0, len*sizeof(int));  25     memset(listPosG, 0, len*sizeof(int));  26     int numB = 0;  27     int numI = 0;  28     int numN = 0;  29     int numG = 0;  30
31     for (int i = 0; i < len; i++)  32  {  33         switch (szBing[i])  34  {  35         case 'B':  36         case 'b':  37             listPosB[numB] = i;  38             numB++;  39             break;  40         case 'I':  41         case 'i':  42             listPosI[numI] = i;  43             numI++;  44             break;  45         case 'N':  46         case 'n':  47             listPosN[numN] = i;  48             numN++;  49             break;  50         case 'G':  51         case 'g':  52             listPosG[numG] = i;  53             numG++;  54             break;  55  }  56  }  57
58     int count = 0;  59
60     int startB;  61     int startI;  62     int startN;  63     int startG;  64     for (int b = 0; b < numB; b++)  65  {  66         startB = listPosB[b];  67
68         for (int i = 0; i < numI; i++)  69  {  70             startI = listPosI[i];  71             if (startI < startB)  72  {  73                 continue;  74  }  75
76             for (int n = 0; n < numN; n++)  77  {  78                 startN = listPosN
;  79                 if (startN < startI)  80  {  81                     continue;  82  }  83
84                 for (int g = 0; g < numG; g++)  85  {  86                     startG = listPosG[g];  87                     if (startG < startN)  88  {  89                         continue;  90  }  91
92                     count++;  93                     if (count > BING_MAX)  94  {  95                         count -= BING_MAX;  96  }  97  }  98  }  99  } 100  } 101
102  free(listPosB); 103  free(listPosI); 104  free(listPosN); 105  free(listPosG); 106
107     return count; 108 }


优化后的代码:

1 #include <cstring>
2 #include <cstdio>
3
4 #define BING_MAX 1000000007
5
6 struct U2  7 {  8     short pos;  9     short next;  10 };  11
12 int Bing(const char* szBing)  13 {  14     if (!szBing || !szBing[0])  15  {  16         return 0;  17  }  18
19     int len = (int)strlen(szBing);  20     U2* listPosB = (U2*)malloc(len*sizeof(U2));  21     U2* listPosI = (U2*)malloc(len*sizeof(U2));  22     U2* listPosN = (U2*)malloc(len*sizeof(U2));  23     U2* listPosG = (U2*)malloc(len*sizeof(U2));  24     memset(listPosB, 0, len*sizeof(int));  25     memset(listPosI, 0, len*sizeof(int));  26     memset(listPosN, 0, len*sizeof(int));  27     memset(listPosG, 0, len*sizeof(int));  28     int numB = 0;  29     int numI = 0;  30     int numN = 0;  31     int numG = 0;  32
33     for (int i = 0; i < len; i++)  34  {  35         switch (szBing[i])  36  {  37         case 'B':  38         case 'b':  39             listPosB[numB].pos = (short)i;  40             numB++;  41             break;  42         case 'I':  43         case 'i':  44             listPosI[numI].pos = (short)i;  45             numI++;  46             break;  47         case 'N':  48         case 'n':  49             listPosN[numN].pos = (short)i;  50             numN++;  51             break;  52         case 'G':  53         case 'g':  54             listPosG[numG].pos = (short)i;  55             numG++;  56             break;  57  }  58  }  59
60     for (int i = 0; i < numB; i++)  61  {  62         for (int j = 0; j < numI; j++)  63  {  64             if (listPosB[i].pos < listPosI[j].pos)  65  {  66                 listPosB[i].next = j;  67                 break;  68  }  69  }  70  }  71
72     for (int i = 0; i < numI; i++)  73  {  74         for (int j = 0; j < numN; j++)  75  {  76             if (listPosI[i].pos < listPosN[j].pos)  77  {  78                 listPosI[i].next = j;  79                 break;  80  }  81  }  82  }  83
84     for (int i = 0; i < numN; i++)  85  {  86         for (int j = 0; j < numG; j++)  87  {  88             if (listPosN[i].pos < listPosG[j].pos)  89  {  90                 listPosN[i].next = j;  91                 break;  92  }  93  }  94  }  95
96     int count = 0;  97     for (int b = 0; b < numB; b++)  98  {  99         for (int i = listPosB[b].next; i < numI; i++) 100  { 101             for (int n = listPosI[i].next; n < numN; n++) 102  { 103                 for (int g = listPosN
.next; g < numG; g++) 104  { 105                     count++; 106                     if (count > BING_MAX) 107  { 108                         count -= BING_MAX; 109  } 110  } 111  } 112  } 113  } 114
115     /*
116  short startB; 117  short startI; 118  short startN; 119  short startG; 120  for (int b = 0; b < numB; b++) 121  { 122  startB = listPosB[b].pos; 123
124  for (int i = 0; i < numI; i++) 125  { 126  startI = listPosI[i].pos; 127  if (startI < startB) 128  { 129  continue; 130  } 131
132  for (int n = 0; n < numN; n++) 133  { 134  startN = listPosN
.pos; 135  if (startN < startI) 136  { 137  continue; 138  } 139
140  for (int g = 0; g < numG; g++) 141  { 142  startG = listPosG[g].pos; 143  if (startG < startN) 144  { 145  continue; 146  } 147
148  count++; 149  if (count > BING_MAX) 150  { 151  count -= BING_MAX; 152  } 153  } 154  } 155  } 156  } 157     */
158
159  free(listPosB); 160  free(listPosI); 161  free(listPosN); 162  free(listPosG); 163
164     return count; 165 }


第三版优化,还是运行时间超过3s,我是真没辙了.

1 #include <cstring>
2 #include <cstdio>
3 #include <assert.h>
4
5 #define BING_MAX 1000000007
6
7 struct U2  8 {  9     short pos;  10     short next;  11 };  12
13 int Bing(const char* szBing, int len)  14 {  15     if (!szBing || !szBing[0])  16  {  17         return 0;  18  }  19
20     U2* listPosB = (U2*)malloc(len*sizeof(U2));  21     U2* listPosI = (U2*)malloc(len*sizeof(U2));  22     U2* listPosN = (U2*)malloc(len*sizeof(U2));  23     U2* listPosG = (U2*)malloc(len*sizeof(U2));  24     memset(listPosB, 0, len*sizeof(int));  25     memset(listPosI, 0, len*sizeof(int));  26     memset(listPosN, 0, len*sizeof(int));  27     memset(listPosG, 0, len*sizeof(int));  28     int numB = 0;  29     int numI = 0;  30     int numN = 0;  31     int numG = 0;  32
33     for (int i = 0; i < len; i++)  34  {  35         if (szBing[i] == 'b')  36  {  37             listPosB[numB].pos = (short)i;  38             numB++;  39  }  40         else if  (szBing[i] == 'i')  41  {  42             listPosI[numI].pos = (short)i;  43             numI++;  44  }  45         else if  (szBing[i] == 'n')  46  {  47             listPosN[numN].pos = (short)i;  48             numN++;  49  }  50         else
51  {  52             listPosG[numG].pos = (short)i;  53             numG++;  54  }  55  }  56
57     int t = 0;  58     for (int i = 0; i < numB; i++)  59  {  60         for (int j = t; j < numI; j++)  61  {  62             if (listPosB[i].pos < listPosI[j].pos)  63  {  64                 listPosB[i].next = t = j;  65                 break;  66  }  67  }  68  }  69
70     t = 0;  71     for (int i = 0; i < numI; i++)  72  {  73         for (int j = t; j < numN; j++)  74  {  75             if (listPosI[i].pos < listPosN[j].pos)  76  {  77                 listPosI[i].next = t = j;  78                 break;  79  }  80  }  81  }  82
83     t = 0;  84     for (int i = 0; i < numN; i++)  85  {  86         for (int j = t; j < numG; j++)  87  {  88             if (listPosN[i].pos < listPosG[j].pos)  89  {  90                 listPosN[i].next = t = j;  91                 break;  92  }  93  }  94  }  95
96     int count = 0;  97     for (int b = 0; b < numB; b++)  98  {  99         for (int i = listPosB[b].next; i < numI; i++) 100  { 101             for (int n = listPosI[i].next; n < numN; n++) 102  { 103                 count += numG - listPosN
.next; 104  } 105  } 106
107         if (count > BING_MAX) 108  { 109             count -= BING_MAX; 110  } 111  } 112
113  free(listPosB); 114  free(listPosI); 115  free(listPosN); 116  free(listPosG); 117
118     return count; 119 }


第四版代码:

1 #include <cstring>
2 #include <cstdio>
3
4 #define BING_MAX 1000000007
5
6 struct U2  7 {  8     int pos;  9     int count;  10 };  11
12 int Bing(const char* szBing, int len)  13 {  14     if (!szBing || !szBing[0])  15  {  16         return 0;  17  }  18
19     U2* listPosB = (U2*)malloc(len*sizeof(U2));  20     U2* listPosI = (U2*)malloc(len*sizeof(U2));  21     U2* listPosN = (U2*)malloc(len*sizeof(U2));  22     U2* listPosG = (U2*)malloc(len*sizeof(U2));  23     memset(listPosB, 0, len*sizeof(int));  24     memset(listPosI, 0, len*sizeof(int));  25     memset(listPosN, 0, len*sizeof(int));  26     memset(listPosG, 0, len*sizeof(int));  27     int numB = 0;  28     int numI = 0;  29     int numN = 0;  30     int numG = 0;  31
32     for (int i = 0; i < len; i++)  33  {  34         if (szBing[i] == 'b')  35  {  36             listPosB[numB].pos = i;  37             numB++;  38  }  39         else if  (szBing[i] == 'i')  40  {  41             listPosI[numI].pos = i;  42             numI++;  43  }  44         else if  (szBing[i] == 'n')  45  {  46             listPosN[numN].pos = i;  47             numN++;  48  }  49         else if  (szBing[i] == 'g')  50  {  51             listPosG[numG].pos = i;  52             numG++;  53  }  54  }  55
56     int b = 0;  57     int i = 0;  58     int n = 0;  59     int g = 0;  60     int t;  61
62     // 每个N之后有多少个G的选择
63     for (n = 0; n < numN; n++)  64  {  65         while (listPosG[g].pos < listPosN
.pos && g < numG)  66  {  67             g++;  68  }  69         listPosN
.count = numG - g;  70  }  71
72     // 每个I之后有多少个NG的选择
73     n = 0;  74     for (i = 0; i < numI; i++)  75  {  76         while (listPosN
.pos < listPosI[i].pos && n < numN)  77  {  78             n++;  79  }  80         listPosI[i].count = 0;  81         for (t = n; t < numN; t++)  82  {  83             listPosI[i].count += listPosN[t].count;  84  }  85  }  86
87     // 每个B之后有多少个ING的选择
88     i = 0;  89     int count = 0;  90     for (int b = 0; b < numB; b++)  91  {  92         while (listPosI[i].pos < listPosB[b].pos && i < numI)  93  {  94             i++;  95  }  96         listPosB[b].count = 0;  97         for (t = i; t < numI; t++)  98  {  99             listPosB[b].count += listPosI[t].count; 100  } 101
102         count += listPosB[b].count; 103         if (count > BING_MAX) 104  { 105             count -= BING_MAX; 106  } 107  } 108
109  free(listPosB); 110  free(listPosI); 111  free(listPosN); 112  free(listPosG); 113
114     return count; 115 }


终于想到正确答案了,原来我一开始就误入歧途了,最早的代码算法复杂度是O(n^4),我将其优化到O(n^2),然后又优化到O(n*log(n)),而最终代码的复杂度是O(n).

1 #define BING_MAX 1000000007
2
3 int Bing(const char* szBing)  4 {  5     int numB = 0;  6     int numI = 0;  7     int numN = 0;  8     int numG = 0;  9     int pos = 0; 10     while (szBing[pos]) 11  { 12         if (szBing[pos] == 'b') 13  { 14             numB++; 15  } 16         else if (szBing[pos] == 'i') 17  { 18             numI += numB; 19  } 20         else if (szBing[pos] == 'n') 21  { 22             numN += numI; 23  } 24         else if (szBing[pos] == 'g') 25  { 26             numG += numN; 27             if (numG > BING_MAX) 28  { 29                 numG -= BING_MAX; 30  } 31  } 32         pos++; 33  } 34
35     return numG; 36 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: