第四章小结

大战1-8

        没错,天梯赛让我自闭的题目,终于ac了。在天梯赛,我的思想是把空格,问号,i和me与大小写处理好,然后将句子的每一个单词放入一个二维数组,然后就很容易用cmp比较can you和could you了。在比赛后我仍使用这思想,敲出来了:

 

  1 #include<iostream>
  2 #include<cstring>
  3 using namespace std;
  4 char ans[1000][1000],a[10000];//ans是答案数组,a用于读入
  5 int vis[1000];//用于标记分隔符前面的空格
  6 int k,hang;//中间变量
  7 int main()
  8 {
  9     int n;
 10     cin>>n;
 11     getchar();
 12     while(n--)
 13     {
 14         memset(ans,-1,sizeof(ans));
 15         memset(vis,0,sizeof(vis));
 16         cin.getline(a,1000);
 17         cout<<a<<endl<<"AI: ";
 18         int h=strlen(a);
 19 
 20         for(int i=0;i<h;i++)
 21         {
 22             if(a[i]=='?')
 23             {
 24                 a[i]='!';
 25             }
 26             else if(isupper(a[i])&&a[i]!='I')//是大写字母而且不是大写i
 27             {
 28                 a[i]=tolower(a[i]);//变成大写
 29             }
 30 
 31         }
 32 
 33         k=0,hang=0;
 34 
 35         for(int i=0;i<h;)
 36         {
 37             char fuzhi[100];//中间变量,用于复制进ans数组
 38             k=0;
 39 
 40             if( isalpha(a[i]) )//是字母,意味着单词出现了
 41             {
 42                 while( i<h && isalpha(a[i]) )//读入单词
 43                 {
 44                     fuzhi[k++]=a[i++];
 45                 }
 46             }
 47 
 48             else if( isdigit(a[i]) )//读入数字
 49             {
 50                 while( i<h && isdigit(a[i]) )
 51                 {
 52                     fuzhi[k++]=a[i++];
 53 
 54                 }
 55 
 56             }
 57             else if(a[i]==' ')//是空格,就把后面多于的空格消掉
 58             {
 59 
 60                 fuzhi[k++]=' ';
 61                 while( i<h && a[i]==' ' )
 62                 i++;
 63             }
 64 
 65             else
 66             {//是分隔符,就得看看前面有没有空格,有的话就标记vis【前面一行】
 67                 fuzhi[k++]=a[i++];
 68                 if( hang>0 && strcmp(ans[hang-1]," ")==0)
 69                 {
 70                     vis[hang-1]=-1;
 71                 }
 72             }
 73 
 74             fuzhi[k]='\0';
 75             if( strcmp(fuzhi," ")==0 && ( i==h || hang==0) )//如果是首尾空格,就继续
 76             {
 77                 continue;
 78             }
 79             //cout<<"复制为"<<fuzhi<<"此时i为"<<i<<endl;
 80             strcpy(ans[hang++],fuzhi);//把东西装进ans数组,然后hang++,继续循环
 81 
 82         }
 83 
 84         for(int i=0;i<hang;i++)
 85         {
 86             if(strcmp(ans[i],"I")==0||strcmp(ans[i],"me")==0)
 87                 strcpy(ans[i],"you");
 88             else if(strcmp(ans[i],"could")==0)
 89             {
 90                 int z=i+1;
 91                 while(vis[z]==-1)//负一就无视
 92                 z++;
 93                 z=z+1;//第一个不是负一的,此时要看看它后面有没有负一
 94                 if(vis[z+1]==-1)
 95                 {
 96                     z=z+1;
 97                     while(vis[z]==-1)
 98                     z++;
 99                 }
100                 if(strcmp(ans[z],"you")==0)
101                 {
102                     strcpy(ans[i],"I");
103                     strcpy(ans[z],"could");
104                 }
105             }
106             else if(strcmp(ans[i],"can")==0)//同上
107             {
108 
109                 int z=i+1;
110                 while(vis[z]==-1)
111                 z++;
112                 z=z+1;
113                 if(vis[z]==-1)
114                 {
115                     z=z+1;
116                     while(vis[z]==-1)
117                     z++;
118                 }
119                 if(strcmp(ans[z],"you")==0)
120                 {
121                     strcpy(ans[i],"I");
122                     strcpy(ans[z],"can");
123                 }
124             }
125         }
126         for(int i=0;i<hang;i++)
127         {
128             if(vis[i]==-1)
129             continue;
130             cout<<ans[i];
131         }
132         cout<<endl;
133     }
134     return 0;
135 }

          但是,过了四个测试点,还有两个段错误,一直debug不出来。老师的方法是对原串进行预处理,把空格,大小写什么的先弄了,最后遍历,判断can(could) you,匹配的时候不改变原串输出i can i could,这样就可以不改变原串的can you could you了,但是我硬要改变要怎么弄呢,于是乎,我学了很多string库封装的函数,翻了好多博客,又敲了两个多小时,没错,string函数太好用了,100多行变成70多行了:

 1 #include<iostream>
 2 using namespace std;
 3 bool isfuhao(char x)//判断是否标点符号
 4 {
 5     if (x<'0'||x>'9'&& x<'A'|| x>'Z'&& x<'a' || x>'z')
 6     return true;
 7     return false;
 8 }
 9 int main()
10 {
11     int n;
12     cin>>n;
13     getchar();
14     while(n--)
15     {
16         string s;
17         getline(cin,s);
18         cout<<s<<endl;
19         while(s[0]==' ') s.erase(s.begin());//删除最前面的空格
20         while(s[s.length()-1]==' ') s.erase(s.end()-1);//删除最后面的空格
21         for(int i=0;i<s.length();i++)
22         {
23             if(s[i]==' '){
24                 while(s[i+1]==' ') s.erase(s.begin()+i+1);//删掉空格后面多的空格
25                 if(isfuhao(s[i+1])){
26                     s.erase(s.begin()+i);//如果后面是标点符号,现在这个空格也删掉
27                 }
28             }
29         }
30         for(int i=0;i<s.length();i++)
31             if(isupper(s[i])&&s[i]!='I')//把除i外大写的换成小写
32                 s[i]=tolower(s[i]);
33 
34         for(int beg=0;;beg++){
35             beg=s.find("can you",beg);//从beg处开始找can you 找到后将c的下标赋给beg
36             if(beg==-1) break;        //没找到,break
37             if(  ( beg==0||isfuhao(s[beg-1]) )&& ( beg+7==s.length()||isfuhao(s[beg+7]) ) )//判断一下能不能换
38             s.replace(beg,7,"A can");//在beg处替换七个字符,替换成A can(换成A是因为不和下面的I冲突)
39         }
40         //换could you i me 都是一样的流程
41         for(int beg=0;;beg++){
42             beg=s.find("could you",beg);
43             if(beg==-1) break;
44             if(  ( beg==0||isfuhao(s[beg-1]) )&& ( beg+9==s.length()||isfuhao(s[beg+9]) ) )
45             s.replace(beg,9,"A could");
46         }
47 
48         for(int beg=0;;beg++){
49             beg=s.find("I",beg);
50             if(beg==-1) break;
51             if(  (beg==0||isfuhao(s[beg-1]))   &&   (beg+1==s.length() || isfuhao(s[beg+1]))   )
52             s.replace(beg,1,"you");
53         }
54 
55         for(int beg=0;;beg++){
56             beg=s.find("me",beg);
57             if(beg==-1) break;
58             if(  (beg==0||isfuhao(s[beg-1]))   &&   (beg+2==s.length() || isfuhao(s[beg+2]))   )
59             s.replace(beg,2,"you");
60         }
61 
62         for(int i=0;i<s.length();i++)//最后把A换回来
63         {
64             if(s[i]=='?') s[i]='!';
65             if(s[i]=='A') s[i]='I';
66         }
67         cout << "AI: " << s << endl;
68     }
69     return 0;
70 }

 串的匹配

   BF算法太简单就不说了,重点是kmp的next数组,next数组的定义很重要,next【j】表示当T[i] != P[j]时,j指针的下一个位置,那么怎么求这个位置呢,这就是kmp的精华,先看看代码:

 

void getNext(String p) {
    next[0] = -1;
    int j = 0;
    int k = -1;
    while (j < p.length - 1) {
       if (k == -1 || p[j] == p[k]) {
           next[++j] = ++k;
       } else {
           k = next[k];
       }
    }
}

 

          我们来看while里面的两个分支,第一个是k==-1或p[j] == p[k]就执行,啥意思呢?

先来看看如果j=0时如果不匹配怎么办

        所以在代码中才会有next[0] = -1;这个初始化。那当p[j] == p[k]的时候,next[j+1]为什么等于 next[j] + 1呢,因为在P[j]之前已经有P[0 ~ k-1] == p[j-k ~ j-1]。这时候现有P[k] == P[j],就可以得到P[0 ~ k-1] + P[k] == p[j-k ~ j-1] + P[j]。

即next[j+1] == k + 1 == next[j] + 1。

  再来看第二个分支,p[j] != p[k]时,k=next【k】;

 

       这样,next数组就弄出来了,其他就没什么难的了。

     接下来的目标:把主席树弄懂,把dfs线段树debug,把十字链表敲出来,还有复习深搜和广搜。如果这些都弄完了的话就去debug一开始的1-8吧。

转载于:https://www.cnblogs.com/qq2210446939/p/10707024.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值