[NOIP2011 普及组] 统计单词数 - 洛谷https://www.luogu.com.cn/problem/P1308
第1行是一个单词字符串,只包含字母;第2行是一个文章字符串,只包含字母和空格。
如果在文章中找到给定的单词,则输出以空格隔开的两个整数,分别表示单词在文章中出现的次数和第1次出现的位置;如果单词在文章中没有出现,则输出 -1。
To
to be or not to be is a question
to
Did the Ottoman Empire lose its power at that time
2 0
-1
本问题为字符串匹配问题,需要注意两个问题。
将所有的字母同一转为为小写或大写即可。
采用首尾补空格的办法解决,例如单词为“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);
- }
- }
绿色为输入,白色为输出。

