(一)题面

计蒜之道2015程序设计大赛初赛第一场——搜狗输入法的分词算法

搜狗输入法最近的用户输入中出现了一种新的输入模式,形如 “0k1234567”,搜狗的工程师发现这一模式后了解到,这是一种新被提出的对于十五进制数字的标记模式,其中 “0k” 是标记进制为15的前缀标记,之后的部分 “1234567” 是实际的十五进制的数字串。

在发现这一标记模式后,搜狗的工程师开始尝试在已有的分词算法上进一步加入对于十五进制数字串的处理,把网页上的这种形式的 15 进制数正确地提取出来。我们知道,标记十五进制的 “0k” 中 k 必须是小写,数字 0 到 14 在这套标记模式下会被依次表示为:0k0, 0k1, ..., 0k9, 0kA, 0kB, 0kC, 0kD, 0kE。也就是说 15 进制数字中只会出现 0-9、k 和 A-E。

值得注意的是,数字表示中不能有多余的 0,比如 0k05 是不能被当做一个十五进制数字的。另外,作为一种约定,当出现 “0k90k8” 时,只有 0k90 是符合期望的十五进制数字,即总是从左至右依次提取出最长的十五进制数字。如果希望表达 0k9 和 0k8 这两个数字的连写情况时,则会被写成 “0k9'0k8” 这一的形式(单引号代表其他任意非数字字符)。

搜狗的工程师希望将用户输入中符合上述要求的所有十五进制数依次输出。你能帮他实现么?

输入格式

输入一行字符串 str (1 ≤ |str| ≤ 106),表示搜狗工程师得到的用户输入。用户输入中的字符一定是数字 (0 - 9) 或大小写英文字母 (a - z, A - Z)。

输出格式

输出包括若干行,每行输出一个提取出的十五进制数(形式如同:0k1234),分别对应输入字符串中含有的若干个符合标记模式的十五进制数字;输出时,请以数字在原字符串中的顺序依次输出。

样例1

输入:

sjfjfhua0kA0000lmNhdhahdfhGgdJG90K10k110k120kF

输出:

0kA0000
0k110

(二)参考源码

 

 1 import java.io.BufferedReader;
 2 import java.io.InputStreamReader;
 3 
 4 public class Main {
 5     // LINE_SEPARATOR is equal to "\r\n" for windows
 6     private static final String LINE_SEPARATOR = System
 7             .getProperty("line.separator");
 8     private static BufferedReader reader = new BufferedReader(
 9             new InputStreamReader(System.in));
10 
11     /**
12      * 
13      * 判断字符character是否是16进制字符
14      */
15     static boolean is16(char character) {
16         if ((character >= '0' && character <= '9')
17                 || (character >= 'A' && character <= 'E')) {
18             return true;
19         }
20         return false;
21     }
22 
23     public static void main(String[] args) throws Exception {
24 
25         char[] inputArray = new char[1000000];
26         // 将所有要输出的结果,放到StringBuilder中,最后一次性输出。如果每找到一个,就输出一个会影响效率
27         StringBuilder builder = new StringBuilder();
28         // 是否找到了16进制数
29         boolean found = false;
30         // 输入序列的字符数,初始化为-1
31         int numberOfcharacter = -1;
32         // 注意:方法int java.io.Reader.read(char[] cbuf) throws
33         // IOException在没有输入时,一直阻塞,所以这里如果使用while,会导致一直运行不到while后面的代码。
34         if ((numberOfcharacter = reader.read(inputArray)) != -1) {
35             for (int i = 0; i < numberOfcharacter;) {
36                 if (found) {
37                     if (!is16(inputArray[i])) {
38                         builder.append(LINE_SEPARATOR);
39                         found = false;
40                         i++;
41                     } else {
42                         builder.append(inputArray[i]);
43                         i++;
44                     }
45                 } else {
46                     // 这里要判断i是否小于numberOfcharacter-2,而且考虑效率,将其作为if语句的最后一个判断条件。
47                     if (inputArray[i] == '0' && inputArray[i + 1] == 'k'
48                             && i < numberOfcharacter - 2) {
49                         if (inputArray[i + 2] == '0') {
50                             // ex:0k0
51                             builder.append("0k0").append(LINE_SEPARATOR);
52                             i = i + 3;
53                         } else if (is16(inputArray[i + 2])) {
54                             // ex:0k2
55                             builder.append("0k").append(inputArray[i + 2]);
56                             found = true;
57                             i = i + 3;
58                         } else {
59                             // ex:0kF
60                             i = i + 3;
61                         }
62                     } else {
63                         i++;
64                     }
65                 }
66             }
67 
68         }
69         if (builder.length() > 0) {
70             System.out.println(builder.toString());
71         }
72     }
73 }
Java