hihoCoder #1871 : Heshen's Account Book-字符串暴力模拟 自闭(getline()函数) (ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction B) 2018 ICPC 北京区域赛现场赛B
Description
Heshen was an official of the Qing dynasty. He made a fortune which could be comparable to a whole country's wealth by corruption. So he was known as the most corrupt official in Chinese history. But Emperor Qianlong liked, or even loved him so much that was not punished during Qianlong's regime even everybody knew he was totally corrupted.
After Qianlong quit his job, his son Jiaqing took the throne. The new Emperor hated Heshen very much, so he threw Heshen into jail and awarded him death immediately after Qianlong died. Of course Jiaqing would not forget to raid Heshen's house for money --- that was the story of "Heshen fell, Jiaqing full."
Jiaqing's man got a notebook from Heshen's home which was obviously an account book.But the text of the book was written in English! Jiaqing thought all numbers in that account book should stand for money. Please find out all numbers for Jiaqing.
The text of the account book consists only lower case letters, spaces, and digits
('0' - '9'). One or several consecutive digits form a number. But Jiaqing only cared about the ACTUAL numbers among all numbers. Only if a number DOESN'T satisfy any of the conditions below, it is an ACTUAL number:
1) The character to the left of the number is a lower case letter, for example: a123
2) The character to the right of the number is a lower case letter, for example: 123b
3) The number has one or more extra leading zeros, such as 01 , 0012….
Please note that if the last character of a line is a digit, and the first character of the next line is also a digit, those two digits are considered consecutive.
Input
There are no more than 200 lines. The length of each line is no more than 1000 characters.
And it is guaranteed that every number's length is no more than 18.
There may be spaces at the end of a line, and those spaces matter.
No blank lines in the input. A line consisting of only spaces is not a blank line.
Output
Print all ACTUAL numbers in a single line in the original order.
Then, count the number of ACTUAL numbers of each line, and print them. A number X only belongs to the line which contains the first digit of X.
Sample Explanation
We assume there is no spaces at the end of each line in the Sample Input.
In the sample input, the '3' at the end of the second line and the '2' at the beginning of the third line are considered consecutive, so "1323" is a number. But this number only belongs to the second line, so the third line has only 2 numbers ---- 14 and 344..- Sample Input
-
a19 01 17b 12 bdc 13 23 14 344 bc
- Sample Output
-
12 1323 14 344 0 2 2
题意就是给你一段文本,让你从里面找出来所有的ACTUAL numbers,就是找出来数字,仅由0-9的数组成,没有字母,并且没有前导零。输出来所有满足条件的数字,然后再输出每一行有多少个数字。
有一个小tip:如果上一行的最后一个是数字,下一行的开头也是数字,要连在一起,计数的时候记到上一行,下一行就不计这个数。
这个题是真的自闭,写得好的(姿势对的)一次就能过,写不好的,写到没脾气也过不了。交了26遍才过。。。
可能是我太捞了,也可能就是不能用getchar,用getchar写的过不了,用getline写的可以过。
数据怎么结束输入,就是输完数据换行之后按Ctrl+Z就可以了。
题目坑点:
1.因为题目上说数字的长度最长不超过18,我一开始眼瞎没看到,写的int,后面改成用字符串存的。
2.上一行最后一个如果为数字,下一行的开头也是数字的话,要连在一起。这里有好几个坑点样例:上一行最后如果满足并且只有一个数字为0,下一行为满足的数字,那么连在一起是不满足的,这是有前导零的情况。如果只有一个零,这是满足的。还有一种是上一行最后是满足情况的数字,但是下一行是不满足的,比如上一行最后为124,下一行开头为3456c,这种事不满足的。然后就是接下来的几行都是数字,比如第一行为erty 56,第二行为2462,第三行为357245,这种是都要连在一起的。还有就是上一行最后是不满足情况的,但是最后一个是数字的,这种是不满足的,举例:上一行最后为c124,下一行开始为45674,这种情况下,45674是不计数的,因为连在一起是不满足情况的。
3.题目上说的是文本仅由小写字母,数字和空格组成,所以要考虑一下空格,如果上一行为r45 (空格)下一行为123,那么123是不受上面的影响的。
4.我感觉数据可能有点迷,也可能是我太捞了,因为题目上说文本只由小写字母,数字和空格组成,但是样例输入的话肯定是需要换行才能输入下一行的吧,要不然怎么输入下一行???我读入数据的时候,用getchar读入,通过判断是否为回车来换行,应该没错吧,因为题目上说了没有空行,只有空格的行不是空行,但是我getchar可以读入空格呀,没毛病呀,老铁。但是我这样并没有写过,不管我程序中间判断字母的时候最后是通过换行判断还是通过长度是否等于该行长度判断,都不对,而且我后面试了不存换行,也写不过,但是我换成getline读入,就过了。特意去查了一下getline,系统默认情况下,getline是一行一行读入,用字符串存数据就可以,回车结束输入,或者读完文件结束。但是从某种方面来讲,测试数据也是通过换行写下一行的,所以讲道理,我用getchar读数据应该也不会错才对,但是我getchar就是过不了,最后改成getline才能过。也可能是我用vector存数据存错了???,不知道啊,真是让人没脾气的暴力模拟题。
可能坑点个人总结的不完整,代码注释里写了,而且一些特殊样例自己也猜出来了,存了一下。贴到下面。
直接代码:
1 //B-字符串暴力模拟-A了 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<bitset> 7 #include<cassert> 8 #include<cctype> 9 #include<cmath> 10 #include<cstdlib> 11 #include<ctime> 12 #include<deque> 13 #include<iomanip> 14 #include<list> 15 #include<map> 16 #include<queue> 17 #include<set> 18 #include<stack> 19 #include<vector> 20 #include<istream> 21 using namespace std; 22 typedef long long ll; 23 typedef long double ld; 24 typedef pair<int,int> pii; 25 26 const double PI=acos(-1.0); 27 const double eps=1e-6; 28 const ll mod=1e9+7; 29 const int inf=0x3f3f3f3f; 30 const int maxn=1000+10; 31 const int maxm=2e5+10; 32 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 33 34 //vector<char> ve[maxn]; 35 vector<string> ans; 36 int num[maxn]; 37 string str[maxn]; 38 string ve[maxn]; 39 40 int main() 41 { 42 char c; 43 int n=0; 44 int tmp=0; 45 // while((c=getchar())!=EOF){ 46 // ve[n].push_back(c); 47 // if(c=='\n') n++; 48 // } 49 while(getline(cin,ve[tmp++])){} 50 // for(int i=0;i<tmp-1;i++){ 51 // for(int j=0;j<str[i].size();j++){ 52 // ve[n].push_back(str[i][j]); 53 // } 54 // ve[n].push_back('\n'); 55 // n++; 56 // } 57 tmp--; 58 // cout<<tmp<<endl; 59 int flag=0,flag1=0,cnt=0,ove=-1,pos=-1;//flag是前导零,数字中有字母的判断,flag1是判断上一行最后一个是不是数字,cnt为当前行数字个数计数,ove是上一行最后是否为满足的数字,pos为最后满足条件的数为第几行 60 string h;//用字符串暂时存数,害怕超范围 61 //for(int i=0;i<n;i++){ 62 for(int i=0;i<tmp;i++){ 63 cnt=0;int len=0; 64 //char pre=*(ve[i].end()-2);//pre为当前行的最后是否为数字,以便来看是否会影响下一行 65 //for(auto it:ve[i]){//遍历 66 for(int j=0;j<ve[i].size();j++){ 67 len++; 68 if(flag1==1) flag=1,flag1=0;//如果上一行的最后一个字母为数字,并且为不满足的条件,举例:c12 69 //if(it>='0'&&it<='9'&&flag!=1){ 70 if(ve[i][j]>='0'&&ve[i][j]<='9'&&flag!=1){ 71 if(h.size()==0) //h+=it; 72 h+=ve[i][j]; 73 else if(h[0]=='0'){//如果存在前导零的条件,就标记flag,清空h,把上一行的去掉,因为多加了。 74 flag=1,h.clear(); 75 num[pos]--;pos=-1;//位置标记赋初值 76 } 77 //else h+=it; 78 else h+=ve[i][j]; 79 } 80 //else if(it==' ') 81 else if(ve[i][j]==' '){ 82 if(ove==1&&h.size()==0){num[pos]--;pos=-1;ove=-1;}//上一行的最后是对的,但是和下一行接起来是错的,上一行要减去 83 if(h.size()!=0){//如果为满足情况的数字 84 ans.push_back(h); 85 h.clear(); 86 cnt++; 87 if(ove==1) cnt--,pos=-1,ove=-1;//如果满足,并且是和上一行接起来的,这一行的不计数 88 } 89 h.clear(),flag=0;//标记清空 90 } 91 //else if(it>='a'&&it<='z') 92 else if(ve[i][j]>='a'&&ve[i][j]<='z'){ 93 if(ove==1&&h.size()!=0){//如果上一行为满足情况的数字 94 if(len==1){//如果下一行的第一个为字母,说明不影响上一行,把上一行的数字存进去 95 ans.push_back(h);//上一行最后满足,当前行第一个为字母,为上一行的满足的 96 ove=-1;pos=-1; 97 } 98 else{ 99 num[pos]--;pos=-1;ove=-1;//如果上一行最后和下一行的接起来是不满足的,那么就要减去上一行的,举例上一行最后为2355,下一行开始为34b 100 } 101 } 102 h.clear(),flag=1; 103 } 104 if(j==ve[i].size()-1){ 105 if(h.size()!=0){ 106 ove=1; 107 if(pos==-1){ 108 pos=i;cnt++; 109 } 110 } 111 else{ 112 if(ve[i][ve[i].size()-1]>='0'&&ve[i][ve[i].size()-1]<='9') flag1=1; 113 ove=-1; 114 } 115 flag=0; 116 } 117 // else if(it=='\n'){ 118 // if(h.size()!=0){//当前行最后为满足的 119 // ove=1;//标记 120 // if(pos==-1){//如果当前位置未标记,说明是满足情况的最一开始的行数,举例,第一行最后为22,下一行为5467,再下一行为3234,标记为22的位置 121 // pos=i;cnt++;//记录位置 122 // } 123 // } 124 // else{ 125 // if(pre>='0'&&pre<='9') flag1=1;//特殊情况,一种是c23这种,下一行开头如果为数字是不成立的,另一种就是前导零,如果上一行最后为0,接下来几行都是数字,那么接下来的几行都是不满足的 126 // ove=-1; 127 // } 128 // flag=0;//标记清空 129 // } 130 } 131 num[i]=cnt; 132 if(i==tmp-1&&h.size()!=0){ 133 ans.push_back(h);//如果为最后一行并且最后的满足,那么就加进去 134 } 135 } 136 vector<string>::iterator it; 137 for(it=ans.begin();it!=ans.end();it++){//输出所有数字 138 if(it!=ans.end()-1) cout<<*it<<" "; 139 else cout<<*it<<endl; 140 } 141 // for(int i=0;i<n;i++)//输出每一行的数字个数 142 // cout<<num[i]<<endl; 143 for(int i=0;i<tmp;i++) 144 cout<<num[i]<<endl; 145 }
这代码写的无语啊。
下面是我想的样例:
1 /* 2 3 in1 4 a19 01 17b 5 12 bdc 13 6 23 14 344 bc 7 8 out 9 12 1323 14 344 10 0 11 2 12 2 13 14 in2 15 a19 01 17b 16 12 bdc 13 0 17 23 14 344 bc 18 19 out 20 12 13 14 344 21 0 22 2 23 2 24 25 in3 26 a19 01 17b 27 12 bdc 13 0 28 cd 14 344 bc 29 30 out 31 12 13 0 14 344 32 0 33 3 34 2 35 36 in4 37 a19 0 17b 38 12 bdc 13 0 39 cd 14 344 bc 40 41 out 42 0 12 13 0 14 344 43 1 44 3 45 2 46 47 in5 48 a19 01 17b 49 12 bdc 13 50 (有一个空格) 23 14 0 bc 51 52 out 53 12 13 23 14 0 54 0 55 2 56 3 57 58 in6 59 4 60 3 61 2 62 1 63 64 out 65 4321 66 1 67 0 68 0 69 0 70 71 in7 72 12 13 73 b 74 v 75 c 76 77 out 78 12 13 79 2 80 0 81 0 82 0 83 84 in8 85 12 13 86 b 87 d 88 0 89 90 out 91 12 13 0 92 2 93 0 94 0 95 1 96 97 in9 98 12 c13 99 21 34 100 101 out 102 12 34 103 1 104 1 105 106 in10 107 0 108 0 109 0 110 111 out 112 0 113 0 114 0 115 116 in11 117 0 118 119 out 120 0 121 1 122 123 in12 124 12 a15 9 125 12356 126 54wf 6 127 128 out 129 12 6 130 1 131 0 132 1 133 134 in13 135 12 0 136 23 137 45 138 67 78 139 140 out 141 12 78 142 1 143 0 144 0 145 1 146 147 in14 148 a19 01 9 149 123 (有一个空格) 150 56t 67 151 152 out 153 9123 67 154 1 155 0 156 1 157 158 */
极度自闭的暴力模拟题,谁头发多或者闲得无聊,这是一个好题。