题目要求

P1308题目链接


分析

这题本身的话,题意就挺烦人,下面分析一下。

本题标签“高性能”,再看看数据范围,暴力匹配必死无疑。我讨厌用char[]慢慢墨迹,Java操作这个很烦人,所以我们就争取用String解决问题吧!!

要做两件事:一是获取Pattern单词在Text的众多单词里出现的次数,二是获取Pattern单词在Text的众多单词里的首次出现位置
我为什么不说是文本的匹配而说单词匹配,看下去,你就明白了。

因为如果说匹配字符串也就可以用String类的indexOf()方法,只是没法直接处理计数,但开个while循环就可以了,也还好办。

要这样也就好了,可惜很恶心,并不是。
它是用空白字符分隔文本为N个单词,我们要匹配单词而不是全文本匹配,对串的普通解法不能解决问题。

这样的话我们的直接思维可能是split(),直接分隔" “就行,但不行。
因为,恶心的是,看提示的一则测试数据,WA一次就发现可能只是任意数量空白字符而已……
所以要用正则表达式”\\s+"进行切分。

但是~~这样的话你交上去只能得30分,其实根本就思路不对,根据获取的数据集3,统计的应该是从开头到那里的indexOf,那直接的思维就是说,先做一个indexOf,在慢慢去计数呗,可惜还不对,因为这样又回到了文本匹配而不是单词匹配。

真让人头秃啊,那继续琢磨,我们把匹配换成" " + pattern + " ",这样就可以保证前后是与其他单词隔开的,即单独成词,对不起,还是不行啊,因为忽略了开头结尾的特判。

这一加上对开头结尾的考虑,代码量激增,必须加很多变量去做过程的处理。具体的看最后的AC代码就行啦,为了调整整个不出Bug,比较麻烦,所以这题让人恶心。

比如我们要先用startWith(pattern + " “)做开头的判断,用endWith(” " + pattern)做结尾的判断,过程中怎么处理balabala,过程怎么进行跃进式的indexOf计数,如何保证第一次就是真的第一次,也会漏结尾的情况balabala,看代码就好了,多说无益。

还有那个“超大容量”,看后面我第二次提交的情况吧,那是什么鬼数据啊,我的记事本和Word都快炸了……好在只有测试数据9一个测试用例这样,不然岂不……太惨了吧……

此题比较恶心,不想多说了。

第一次提交——WA

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String pattern = scanner.nextLine();String[] text_array = scanner.nextLine().split(" ");int counter = 0, index = -1;for (int i = 0; i < text_array.length; i++) {String s = text_array[i];if (s.equalsIgnoreCase(pattern)) {counter++;if (index == -1) {index = i;}}}if (index == -1) {System.out.println(-1);} else {System.out.println(counter + " " + index);}scanner.close();}
}

错因前面分析了,就不说了,一看就知道的。

分享一下测试数据3:
in
u
tIXHUguyz PZYAJL BIv NAPoemaJ aTF LOvhV m s LSa n xDn mQnO T ettIq T AL fG B Xme t fct U tQ d

out
1 92

第二次提交——MLE

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String pattern = scanner.nextLine().toUpperCase(), text = scanner.nextLine().toUpperCase();int length = pattern.length(), counter = 0, firstIndex = -1, tempIndex = -1;boolean endFlag = false;if (text.startsWith(pattern + " ")) {counter++;firstIndex = 0;pattern = " " + pattern + " ";tempIndex = text.indexOf(pattern);}if (text.endsWith(" " + pattern)) {counter++;endFlag = true;}pattern = " " + pattern + " ";if (counter == 0) {firstIndex = tempIndex = text.indexOf(pattern);}while (tempIndex != -1) {text = text.substring(tempIndex + length);tempIndex = text.indexOf(pattern);counter++;}if (firstIndex == -1) {if (endFlag) {System.out.println(1 + " " + (text.length()-1));} else {System.out.println(-1);}} else {System.out.println(counter + " " + (firstIndex+1));}scanner.close();}
}

这个测试数据9……我真没法Share,太大了,这就是我说的超大容量……
这样吧,我把文本数据导进了Word,我先进的电脑卡爆了,加载的数据:

当然这在现在的海量文本数据里面微乎其微,但你要知道这只是一个简单的OJ题啊,这么大的数据量,用Java不得炸裂!!

但我们转而思考自身可能引发超时超内存的问题:数组!!
我们没开数组啊??但String本身不就有数组吗!!!
恍然大悟,我们开了太多substring()了啊,删去就好,换一个indexOf()的重载方法就好!!!

乌拉乌拉乌拉!!!

第三次提交——AC

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String pattern = scanner.nextLine().toUpperCase(), text = scanner.nextLine().toUpperCase();int length = pattern.length(), counter = 0, firstIndex = -1, tempIndex = -1;boolean endFlag = false;if (text.startsWith(pattern + " ")) {counter++;firstIndex = 0;pattern = " " + pattern + " ";tempIndex = text.indexOf(pattern);}if (text.endsWith(" " + pattern)) {counter++;endFlag = true;}pattern = " " + pattern + " ";if (counter == 0) {firstIndex = tempIndex = text.indexOf(pattern);}while (tempIndex != -1) {tempIndex = text.indexOf(pattern, tempIndex+length);counter++;}if (firstIndex == -1) {if (endFlag) {System.out.println(1 + " " + (text.length()-1));} else {System.out.println(-1);}} else {System.out.println(counter + " " + (firstIndex+1));}scanner.close();}
}

总结

  • 在处理一个问题的时候,其实稍加变换解决思路就能大有改观。
  • 解决问题就是根据已知,不断转化转化再转化,直到转化出我们需要的条件,再求解。
  • Java的API博大精深,不断研究,总会有新收获呢。

不知道大家可有收获?今年是大年初一,新春快乐@All !!!

超大容量文本的单词统计(洛谷P1308题题解,Java语言描述)相关推荐

  1. 线性存储的最短平均检索时间(洛谷P1253题题解,Java语言描述)

    题目要求 P1253题目链接 分析 很像 ~洛谷P1223题题解~,也是一种类似SJF的贪心法. 排个序,由于两个不大于10000的数,乘起来还是int,就使用int属性吧. 数据量小,所以Scann ...

  2. 队列模拟约瑟夫问题(洛谷P1996题题解,Java语言描述)

    题目要求 P1996题目链接 分析 以前就研究过"约瑟夫环"问题: <单循环链表求解约瑟夫环问题(Java语言描述)> <杀人游戏~约瑟夫环(洛谷P1145题题解 ...

  3. 去空白符的大文本字符统计(洛谷P5015题题解,Java语言描述)

    题目要求 P5015题目链接 分析 字符串中的字符统计,不含换行符和空白字符,那就正好用Scanner的nextLine(),就自动去了换行符. 接下来每读进来一行String.就调用replaceA ...

  4. 枚举求解单词方阵(洛谷P1101题题解,Java语言描述)

    题目要求 P1101题目链接 分析 可以用DFS做,但我立下了个Flag,所以就用了朴素的枚举来做.... 结果,我的天哪,做了好几个小时-- 其实这种地图题,真的适合 DFS or BFS or D ...

  5. 统计犁过的田の面积(洛谷P2956题题解,Java语言描述)

    题目要求 P2956题目链接 分析 耕田就是开一个二维数组,暴力的进行统计,最后得到结果. --水题--不说啦,看代码就好了. AC代码(Java语言描述) import java.util.Scan ...

  6. 快速排序+统计→奶牛的耳语(洛谷P1296题题解,Java语言描述)

    题目要求 P1296题目链接 分析 这红题--不太好做啊啊哈哈-- 输入的奶牛位置不一定是有序的,要排个序,用内置的快排就行-- 读入完调内置排序算法排一下序,max存能与第i头牛交流的坐标编号最大的 ...

  7. 统计方格区域内正方形和长方形的个数(洛谷P1548题题解,Java语言描述)

    题目要求 P1548题目要求 分析 这题,一看就懵,因为一看就需要推公式,很麻烦-- 此时发现本题是洛谷红题哈哈哈,还没"高性能"标签,那就暴力吧!!! 注意只要区域是正方形就不是 ...

  8. 麦森数(洛谷P1045题题解,Java语言描述)

    题目要求 题目链接 分析 这题挺经典的,快速幂取模算法,如果求出大数再取模就可能T掉. 之前有篇文章写了这个算法:<快速幂算法详解&&快速幂取模算法详解> 既然是Java, ...

  9. 快速幂||取余运算【模板】(洛谷P1226题题解,Java语言描述)

    题目要求 P1226题目链接 分析 标准的快速幂取模算法板子,之前这个算法我在这篇文章中讲过了:<快速幂算法详解&&快速幂取模算法详解>. 这里选择使用比较简单的API实现 ...

最新文章

  1. 《2021全球脑科学发展报告》发布
  2. matlab怎么将一个矩阵转化为灰度图
  3. Java常量池理解与总结
  4. Andorid获取状态栏高度
  5. linux将日期和日历信息追加到文件中_Linux常用指令
  6. php 现代排序_这就是现代PHP的样子
  7. h5 做app时和原生交互的小常识。
  8. 做到这 3 点,斩获 BAT Offer 不是梦
  9. 少林寺步入 5G 时代!
  10. linux 报错 bash ‘/bin/sh: Syntax error: “(” unexpected
  11. Android面试题整理【转载】
  12. 选择目录或选择文件(PyQt或Qt for python)
  13. html加拼音注释,满江红岳飞全文带拼音(注释+译文)
  14. tcp 粘包是怎么产生的?
  15. java jbutton数组_java-JButton需要显示图像数组
  16. xy坐标转换经纬度C语言,(转载)经纬度与西安80,北京54的坐标系转换(C# 实现)...
  17. 天翼网关 ddns设置_UCloud物理云网关百G级集群设计实践
  18. CentOS 7.6安装使用Ansible(三):Ansible Playbook和变量类型
  19. 餐厅扫码点餐怎么弄_分享扫码点餐小程序开发制作方法
  20. 一周AI看点 | 北航设立全国首个人工智能专业,前IBM沃森首席科学家任京东副总裁

热门文章

  1. Oracle 表备份还原
  2. Mac本如何卸载MySQL
  3. 515Nod 1126 求递推序列的第n项【矩阵快速幂】
  4. Notes of fwt
  5. Docker(4)-容器互联与端口映射
  6. yum 安装mysql数据库
  7. 获得当前字符串的宽度
  8. Fiddler中session的请求/响应类型与图标对照表
  9. Path Sum I, II
  10. Context 之我见