统计单词数

一 原问题链接

[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,继续搜索。

六 算法实现

package p1308;

import java.util.Scanner;

public class P1308 {
    // 两个字符串长度
    static int len1;
    static int len2;

    // 全部大写转小写
    static void tolower(char a[]) {
        for (int i = 0; i < a.length; i++)
            if (a[i] >= 'A' && a[i] <= 'Z')
                a[i] += 32;
    }

    // 模式匹配BF算法
    static int BF(char w[], char s[], int pos) {
        int i = pos;
        int j = 0; // 下标从 0 开始
        while (j < len1 && i < len2) {
            if (s[i] == w[j]) {
                i++;
                j++;
            } else {
                i = i - j + 1;
                j = 0;
            }
        }
        if (j >= len1) // 匹配成功
            return i - len1;
        return -1;
    }

    public static void main(String[] args) {
        char word[] = new char[16];
        char sentence[] = new char[1000010];
        Scanner scanner = new Scanner(System.in);
        String tempWord = scanner.nextLine();
        // 输入时,0单元空出来不存储
        for (int i = 0; i < tempWord.length(); i++) {
            word[i + 1] = tempWord.charAt(i);
        }

        String tempSentence = scanner.nextLine();
        // 输入时,0单元空出来不存储
        for (int i = 0; i < tempSentence.length(); i++) {
            sentence[i + 1] = tempSentence.charAt(i);
        }

        word[0] = ' '; // 首尾补空格
        len1 = tempWord.length();
        word[++len1] = ' ';
        word[++len1] = '\0';
        sentence[0] = ' '; // 首尾补空格
        len2 = tempSentence.length();
        sentence[++len2] = ' ';
        sentence[++len2] = '\0';
        tolower(word);
        tolower(sentence);
        int posfirst = BF(word, sentence, 0); // 记录单词首次出现的位置
        if (posfirst == -1) {
            System.out.println(-1);
            return;
        }
        int cnt = 1; // 能走到这说明单词已出现一次了
        int t = posfirst + len1 - 1;
        while (t < len2) {
            t = BF(word, sentence, t);
            if (t == -1)
                break;
            cnt++;
            t = t + len1 - 1;
        }
        System.out.print(cnt + " " + posfirst);
    }
}

七 测试

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

1 测试一

2 测试二

统计单词数_第1张图片

你可能感兴趣的:(数据结构与算法,算法,数据结构)