鱼C论坛

 找回密码
 立即注册
查看: 1181|回复: 8

[已解决]一个字符串匹配的问题

[复制链接]
发表于 2022-4-26 21:36:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
题目 : https://www.luogu.com.cn/problem/P1308
我的代码 :
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. //全部改成小写
  4. void low(string &s){
  5.         for(int i = 0; i < s.size(); i++){
  6.                 s[i] = tolower(s[i]);
  7.         }
  8. }
  9. string target, sentence;

  10. int main(){
  11.         ios::sync_with_stdio(false);

  12.         cin >> target >> sentence;
  13.         string &s = sentence;
  14.         string &t = target;
  15.         low(t); low(s);
  16.         //匹配整个单词, 不是一个包含一个的
  17.         target = ' ' + target + ' ';
  18.         sentence = ' ' + sentence + ' ';
  19.         
  20.         if(sentence.find(target) == -1){//第一次匹配不到直接退
  21.                 cout << "-1";
  22.                 return 0;
  23.         }
  24.         else{
  25.                 int pos = sentence.find(target);
  26.                 int c = 0, p = pos; //c是计数器, p是第一次匹配到的位置
  27.                 while(pos != -1){
  28.                         c++;
  29.                         pos = sentence.find(target, pos-1);
  30.                 }
  31.                 cout << c << ' ' << p;
  32.         }
  33.         return 0;
复制代码

感觉我写的挺对 , 但是输出不尽人意 . 我的代码哪里有问题呢
最佳答案
2022-4-27 08:26:50
柿子饼同学 发表于 2022-4-26 22:53
谢谢回答 , 但是有几个不理解的地方...
之前不是判断过第一次匹不匹配了嘛(22行) , 为什么29行要再看 ...

你的不解的地方:
(一)之前不是判断过第一次匹不匹配了嘛(22行) , 为什么29行要再看一次?
解:这个你可以忽略,因为我没有注意上面,重写了一次匹配。
(二)为啥 c 初始化为 1 就可以?
解:因为如你所说,你上面已经匹配到了至少一次,所以 c 应该从 1 次算起,否则永远少一个。
(三)为啥 34 行 find(target, pos + 1) pos 要加一(我知道是因为加了一个空格, 只是不知道find返回的
值是sentence发现target的第一个字母的位置还是末尾的位置
解:比如 pos 是 13(表示第 13 个位置上发现句子)那么 pos + 1 就是 14,接下来从第 14 位置开始匹配。
(四)另外 , 如果函数的参数是一个引用, 可不可以直接传入变量名呢(就像上面的改小写函数)
解:哈哈哈,这就是我觉得你的代码有点奇怪的地方,如你所说,可以的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-26 22:13:35 | 显示全部楼层
稍微更改一下:
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. //全部改成小写
  4. void low(string& s) {
  5.     for (int i = 0; i < s.size(); i++) {
  6.         s[i] = tolower(s[i]);
  7.     }
  8. }
  9. string target, sentence;

  10. int main() {
  11.     ios::sync_with_stdio(false);

  12.     cin >> target >> sentence;
  13.     string& s = sentence;
  14.     string& t = target;
  15.     low(t); low(s);
  16.     //匹配整个单词, 不是一个包含一个的
  17.     target = ' ' + target + ' ';
  18.     sentence = ' ' + sentence + ' ';

  19.     if (sentence.find(target) == -1) {//第一次匹配不到直接退
  20.         cout << "-1";
  21.         return 0;
  22.     }
  23.     else {
  24.         int pos = sentence.find(target);
  25.         int c = 0, p = pos;
  26.         if (pos != string::npos) { // <---------------------------
  27.             c = 1;                 // <---------------------------
  28.             p = pos;               // <---------------------------
  29.             while (pos != string::npos) { // <---------------------------
  30.                 c++;               // <---------------------------
  31.                 pos = sentence.find(target, pos + 1); // <---------------------------

  32.             }
  33.         }
  34.         cout << c << ' ' << p;
  35.     }
  36.     return 0;
  37. }
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
柿子饼同学 + 5 + 5

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2022-4-26 22:53:12 | 显示全部楼层
本帖最后由 柿子饼同学 于 2022-4-26 22:54 编辑


谢谢回答 , 但是有几个不理解的地方...
之前不是判断过第一次匹不匹配了嘛(22行) , 为什么29行要再看一次
为啥 c 初始化为 1 就可以
为啥 34 行 find(target, pos + 1) pos 要加一(我知道是因为加了一个空格, 只是不知道find返回的
值是sentence发现target的第一个字母的位置还是末尾的位置
感谢大佬
另外 , 如果函数的参数是一个引用, 可不可以直接传入变量名呢(就像上面的改小写函数)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-26 23:21:44 | 显示全部楼层
本帖最后由 jackz007 于 2022-4-26 23:34 编辑
  1. #include <string>
  2. #include <iostream>

  3. using namespace std                                                   ;

  4. //全部改成小写
  5. void low(string & s)
  6. {
  7.         for(int i = 0 ; i < s . size() ; i ++) s[i] = tolower(s[i])   ;
  8. }

  9. int main()
  10. {
  11.         string target , sentence                                      ;
  12.         int c , p , pos                                               ;
  13.         getline(cin , target)                                         ;
  14.         getline(cin , sentence)                                       ;
  15.         low(target)                                                   ;
  16.         low(sentence)                                                 ;
  17.         target = ' ' + target + ' '                                   ;
  18.         sentence = ' ' + sentence + ' '                               ;
  19.         p = pos = sentence . find(target , 0)                         ;
  20.         for(c = 0 ; pos != -1 ; ) {
  21.                 c ++                                                  ;
  22.                 pos = sentence . find(target , pos + target . size()) ;
  23.         }
  24.         if(c) cout << c << " " << p << endl                           ;
  25.         else cout << "-1" << endl                                     ;
  26. }
复制代码

        编译、运行实况:
  1. D:\[00.Exercise]\[C]\cin>g++ -o x x.c

  2. D:\[00.Exercise]\[C]\cin>x
  3. To
  4. to be or not to be is a question
  5. 2 0

  6. D:\[00.Exercise]\[C]\cin>x
  7. to
  8. Did the Ottoman Empire lose its power at that time
  9. -1

  10. D:\[00.Exercise]\[C]\cin>
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-27 08:26:50 From FishC Mobile | 显示全部楼层    本楼为最佳答案   
柿子饼同学 发表于 2022-4-26 22:53
谢谢回答 , 但是有几个不理解的地方...
之前不是判断过第一次匹不匹配了嘛(22行) , 为什么29行要再看 ...

你的不解的地方:
(一)之前不是判断过第一次匹不匹配了嘛(22行) , 为什么29行要再看一次?
解:这个你可以忽略,因为我没有注意上面,重写了一次匹配。
(二)为啥 c 初始化为 1 就可以?
解:因为如你所说,你上面已经匹配到了至少一次,所以 c 应该从 1 次算起,否则永远少一个。
(三)为啥 34 行 find(target, pos + 1) pos 要加一(我知道是因为加了一个空格, 只是不知道find返回的
值是sentence发现target的第一个字母的位置还是末尾的位置
解:比如 pos 是 13(表示第 13 个位置上发现句子)那么 pos + 1 就是 14,接下来从第 14 位置开始匹配。
(四)另外 , 如果函数的参数是一个引用, 可不可以直接传入变量名呢(就像上面的改小写函数)
解:哈哈哈,这就是我觉得你的代码有点奇怪的地方,如你所说,可以的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-27 13:24:40 | 显示全部楼层
jackz007 发表于 2022-4-26 23:21
编译、运行实况:

谢谢回答~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-27 13:25:10 | 显示全部楼层
傻眼貓咪 发表于 2022-4-27 08:26
你的不解的地方:
(一)之前不是判断过第一次匹不匹配了嘛(22行) , 为什么29行要再看一次?
解:这个 ...

okok谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-27 15:30:21 From FishC Mobile | 显示全部楼层
本帖最后由 傻眼貓咪 于 2022-4-27 15:32 编辑
柿子饼同学 发表于 2022-4-27 13:25
okok谢谢


你的代码其实也不正确,cin 只读取单词,不会读取整行。用 getline(cin, str)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-27 16:17:39 From FishC Mobile | 显示全部楼层
  1. #include <iostream>
  2. #include <cctype>

  3. void lower(std::string &str) {
  4.         for (char &c: str) c = tolower(c);
  5. }

  6. int main() {

  7.         std::string target;
  8.         std::string sentence;
  9.        
  10.         std::cin >> target;
  11.         getc(stdin);
  12.         std::getline(std::cin, sentence);
  13.        
  14.         lower(target);
  15.         lower(sentence);
  16.        
  17.         int count = 0, pos = 0, p = -1;
  18.        
  19.         if (sentence.find(target) == std::string::npos) {
  20.                 std::cout << p;
  21.         }
  22.         else {
  23.                 p = pos = sentence.find(target);
  24.                 while (pos != std::string::npos) {
  25.                         count++;
  26.                         pos = sentence.find(target, pos+1);
  27.                 }
  28.                 std::cout << count << " " << p;
  29.         }
  30.         return 0;
  31. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-19 18:32

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表