• 统计单词数


    一 原问题链接

    [NOIP2011 普及组] 统计单词数 - 洛谷https://www.luogu.com.cn/problem/P1308

    二 输入和输出

    1 输入

    第1行是一个单词字符串,只包含字母;第2行是一个文章字符串,只包含字母和空格。

    2 输出

    如果在文章中找到给定的单词,则输出以空格隔开的两个整数,分别表示单词在文章中出现的次数和第1次出现的位置;如果单词在文章中没有出现,则输出 -1。

    三 输入和输出样例

    1 输入样例

    To

    to be or not to be is a question

    to

    Did the Ottoman Empire lose its power at that time

    2 输出样例

    2 0

    -1 

    四 分析

    本问题为字符串匹配问题,需要注意两个问题。

    1 不区分大小写

    将所有的字母同一转为为小写或大写即可。

    2 完全匹配

    采用首尾补空格的办法解决,例如单词为“Abc”,文章为“xYabc aBc”,首先将其全部转换为小写字母,然后在单词和文章的首尾分别补空格,单词为“ abc ”,文章为“ xyabc abc ”,空格为不可见字符。这样就可以在文章中查找单词,保证完全匹配。

    五 算法设计

    1 读入单词和文章,首尾分别补空格。

    2 将单词和文章全部转换为小写字母。

    3 在文章中查找单词首次出现的位置 posfirst,如果查询失败,则输出 -1,算法结束。

    4 让 t = posfirst + len1-1,出现次数 cnt =1。如果 t < len2,则从 t 位置开始在文章中查找单词,如果匹配成功,t = BF(word,sentence,t),则 cnt++,更新 t = t+len1-1,继续搜索。

    六 算法实现

    1. package p1308;
    2. import java.util.Scanner;
    3. public class P1308 {
    4. // 两个字符串长度
    5. static int len1;
    6. static int len2;
    7. // 全部大写转小写
    8. static void tolower(char a[]) {
    9. for (int i = 0; i < a.length; i++)
    10. if (a[i] >= 'A' && a[i] <= 'Z')
    11. a[i] += 32;
    12. }
    13. // 模式匹配BF算法
    14. static int BF(char w[], char s[], int pos) {
    15. int i = pos;
    16. int j = 0; // 下标从 0 开始
    17. while (j < len1 && i < len2) {
    18. if (s[i] == w[j]) {
    19. i++;
    20. j++;
    21. } else {
    22. i = i - j + 1;
    23. j = 0;
    24. }
    25. }
    26. if (j >= len1) // 匹配成功
    27. return i - len1;
    28. return -1;
    29. }
    30. public static void main(String[] args) {
    31. char word[] = new char[16];
    32. char sentence[] = new char[1000010];
    33. Scanner scanner = new Scanner(System.in);
    34. String tempWord = scanner.nextLine();
    35. // 输入时,0单元空出来不存储
    36. for (int i = 0; i < tempWord.length(); i++) {
    37. word[i + 1] = tempWord.charAt(i);
    38. }
    39. String tempSentence = scanner.nextLine();
    40. // 输入时,0单元空出来不存储
    41. for (int i = 0; i < tempSentence.length(); i++) {
    42. sentence[i + 1] = tempSentence.charAt(i);
    43. }
    44. word[0] = ' '; // 首尾补空格
    45. len1 = tempWord.length();
    46. word[++len1] = ' ';
    47. word[++len1] = '\0';
    48. sentence[0] = ' '; // 首尾补空格
    49. len2 = tempSentence.length();
    50. sentence[++len2] = ' ';
    51. sentence[++len2] = '\0';
    52. tolower(word);
    53. tolower(sentence);
    54. int posfirst = BF(word, sentence, 0); // 记录单词首次出现的位置
    55. if (posfirst == -1) {
    56. System.out.println(-1);
    57. return;
    58. }
    59. int cnt = 1; // 能走到这说明单词已出现一次了
    60. int t = posfirst + len1 - 1;
    61. while (t < len2) {
    62. t = BF(word, sentence, t);
    63. if (t == -1)
    64. break;
    65. cnt++;
    66. t = t + len1 - 1;
    67. }
    68. System.out.print(cnt + " " + posfirst);
    69. }
    70. }

    七 测试

    绿色为输入,白色为输出。

    1 测试一

    2 测试二

  • 相关阅读:
    建站选择免费虚拟主机的六大误区
    物理场仿真教程(一)——Ubuntu下Salome_meca 软件安装
    经典排序算法总结
    AVL 平衡二叉搜索树
    虚拟电厂可视化大屏,深挖痛点精准减碳
    用Rust手把手编写一个Proxy(代理), TLS加密通讯
    RK3588平台开发系列讲解(CAN篇)CAN FD 开发文档
    【爬虫】爬虫基础
    【C++设计模式之状态模式:行为型】分析及示例
    uniapp实现App弹窗更新升级(完整版)热更新
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/126089636