- 你对本章内容的小结
- 完成作业或实践时解决困难的经验分享
- 这段时间,你参考了哪些值得向大家分享的资料?每一项推荐都请说明推荐理由及列出相关链接(或书目名称,具体页码)
- 目前学习过程中存在的困难,待解决或待改进的问题
- 上次博客确定的目标达到了吗?如果没达到,请分析原因
- 接下来的目标
一、你对本章内容的小结
第4章主要学习了串、数组
串主要学习了有关 模式匹配算法 的两种算法:T(n)=O(m*n)的BF算法 和 T(n)=O(m+n)的KMP算法,
KMP算法难在求出 模式的next数组。(即求next数组时的思想)
数组主要学习了 怎么求具体下标的元素的地址 以及 如何用一维数组将一些特殊矩阵(如对称矩阵、三角矩阵、对角矩阵、稀疏矩阵等)进行压缩存储。
二、完成作业或实践时解决困难的经验分享
先上修正前的代码:
1 #include<iostream> 2 using namespace std; 3 4 5 void getnext(string t, int *next); 6 int match(string S, string T, const int *next); 7 8 9 int main()//7-1 串的模式匹配 10 { 11 // freopen("input.txt","r",stdin); 12 // freopen("output.txt","w",stdout); 13 14 15 string S; 16 string T; 17 cin>>S; 18 cin>>T; 19 20 21 int next[T.length()]; 22 getnext(T,next); 23 24 25 cout<<match(S,T,next); 26 27 28 return 0; 29 } 30 31 32 33 34 void getnext(string t, int *next) 35 { 36 next[0]=-1; 37 for(int i=0,j=-1; i<t.length();) 38 { 39 if(j==-1||t[i]==t[j]) 40 { 41 i++;j++; 42 next[i]=j; 43 } 44 else j=next[j]; 45 } 46 } 47 48 49 int match(string S, string T, const int *next) 50 { 51 int i=0,j=0; 52 for(;i<S.length()&&j<T.length();) 53 { 54 if(j==-1||S[i]==T[j]) 55 { 56 i++;j++; 57 } 58 else 59 { 60 j=next[j]; 61 } 62 } 63 if(j==T.length()) return i-T.length()+1; 64 else return 0; 65 }
这是我最开始做PTA第4章作业的串的模式匹配的时候用KMP算法写的代码,
这是个有点错的代码。
修正后的代码:
1 #include<iostream> 2 using namespace std; 3 4 5 void getnext(string t, int *next); 6 int match(string S, string T, const int *next); 7 8 9 int main()//7-1 串的模式匹配 10 { 11 // freopen("input.txt","r",stdin); 12 // freopen("output.txt","w",stdout); 13 14 15 string S; 16 string T; 17 cin>>S; 18 cin>>T; 19 20 21 int next[T.length()]; 22 getnext(T,next); 23 24 25 cout<<match(S,T,next); 26 27 28 return 0; 29 } 30 31 32 33 34 void getnext(string t, int *next) 35 { 36 next[0]=-1; 37 for(int i=0,j=-1; i<(int)t.length();) 38 { 39 if(j==-1||t[i]==t[j]) 40 { 41 i++;j++; 42 next[i]=j; 43 } 44 else j=next[j]; 45 } 46 } 47 48 49 int match(string S, string T, const int *next) 50 { 51 int i=0,j=0; 52 for(;i<(int)S.length()&&j<(int)T.length();) 53 { 54 if(j==-1||S[i]==T[j]) 55 { 56 i++;j++; 57 } 58 else 59 { 60 j=next[j]; 61 } 62 } 63 if(j==(int)T.length()) return i-T.length()+1; 64 else return 0; 65 }
这是我修改过后的代码,可以看到我只是在 字符串的长度 前加了(int)进行类型转换,简单来说,就是
负数 不能与 字符数组的strlen(s) 以及 字符串的s.length 进行比较,
或者说 有符号整型中的负数 不能与 无符号整型 进行比较。
1 #include<iostream> 2 #include<string.h> 3 using namespace std; 4 5 6 const int MAXSIZE=1002; 7 8 9 void change2(char *ch);//空格 10 void change3(char *ch);//大写变小写 11 void change4_6(char *ch);//I和me变成you以及can you变成I can 12 void change5(char *ch);//?变成! 13 bool punctuation(char ch);//判断标点符号 14 15 16 int main()//7-2 AI核心代码 17 { 18 // freopen("input.txt","r",stdin); 19 // freopen("output.txt","w",stdout); 20 int n=0; 21 cin>>n; 22 cin.ignore(10,‘\n‘); 23 24 25 char a[n][4*MAXSIZE]; 26 27 28 for(int i=0; i<n; i++) 29 { 30 cin.getline(a[i],MAXSIZE); 31 } 32 33 34 for(int i=0; i<n; i++) 35 { 36 cout<<a[i]<<endl; 37 cout<<"AI: "; 38 39 40 change2(a[i]); 41 change3(a[i]); 42 change4_6(a[i]); 43 change5(a[i]); 44 45 46 cout<<a[i]; 47 48 49 if(i!=n-1) 50 cout<<endl; 51 } 52 53 54 return 0; 55 } 56 57 58 59 60 void change2(char *ch)//空格 61 { 62 int k=0; 63 for(int i=0; ch[i]!=‘\0‘; i++)//前空格 64 { 65 if(ch[i]==‘ ‘) 66 k++; 67 else break; 68 } 69 for(int i=k,j=0; ch[i]!=‘\0‘; i++,j++) 70 { 71 ch[j]=ch[i]; 72 } 73 ch[strlen(ch)-k]=‘\0‘; 74 75 76 for(int i=0,j=0; ch[i]!=‘\0‘; i++)//中空格 77 { 78 if(ch[i]!=‘ ‘||ch[i-1]!=‘ ‘) 79 { 80 ch[j]=ch[i]; 81 j++; 82 k=j; 83 } 84 } 85 ch[k]=‘\0‘; 86 87 88 for(int i=0,j=0; ch[i]!=‘\0‘; i++)//标点前的空格 89 { 90 if(!(ch[i]==‘ ‘&&punctuation(ch[i+1]))) 91 { 92 ch[j]=ch[i]; 93 j++; 94 k=j; 95 } 96 } 97 ch[k]=‘\0‘; 98 99 100 if(ch[strlen(ch)-1]==‘ ‘) ch[strlen(ch)-1]=‘\0‘;//后空格 101 } 102 103 104 void change3(char *ch)//大写变小写 105 { 106 for(int i=0; ch[i]!=‘\0‘; i++) 107 { 108 if(‘A‘<=ch[i]&&ch[i]<=‘Z‘&&ch[i]!=‘I‘) 109 ch[i]=ch[i]+32; 110 } 111 } 112 113 114 void change4_6(char *ch)//can you变成I can 以及 I和me变成you 115 { 116 char m[4*strlen(ch)]; 117 int k=0; 118 for(int i=0,j=0; ch[i]!=‘\0‘;) 119 { 120 if((strlen(ch)-i)>=7&&(i==0||punctuation(ch[i-1]))&&ch[i]==‘c‘&&ch[i+1]==‘a‘&&ch[i+2]==‘n‘&&ch[i+3]==‘ ‘&&ch[i+4]==‘y‘&&ch[i+5]==‘o‘&&ch[i+6]==‘u‘&&punctuation(ch[i+7])) 121 { 122 m[j]=‘I‘;m[j+1]=‘ ‘;m[j+2]=‘c‘;m[j+3]=‘a‘;m[j+4]=‘n‘; 123 i=i+7;j=j+5; 124 k=j; 125 } 126 else if((i==0||punctuation(ch[i-1]))&&ch[i]==‘I‘&&punctuation(ch[i+1])) 127 { 128 m[j]=‘y‘;m[j+1]=‘o‘;m[j+2]=‘u‘; 129 i++;j=j+3; 130 k=j; 131 } 132 else if((i==0||punctuation(ch[i-1]))&&ch[i]==‘m‘&&ch[i+1]==‘e‘&&punctuation(ch[i+2])) 133 { 134 m[j]=‘y‘;m[j+1]=‘o‘;m[j+2]=‘u‘; 135 i=i+2;j=j+3; 136 k=j; 137 } 138 else 139 { 140 m[j]=ch[i]; 141 i++;j++; 142 k=j; 143 } 144 } 145 146 147 for(int i=0; i<k; i++) 148 { 149 ch[i]=m[i]; 150 } 151 ch[k]=‘\0‘; 152 } 153 154 155 void change5(char *ch)//?变成! 156 { 157 for(int i=0; ch[i]!=‘\0‘; i++) 158 { 159 if(ch[i]==‘?‘) ch[i]=‘!‘; 160 } 161 } 162 163 164 bool punctuation(char ch)//判断标点符号 165 { 166 return (!(‘0‘<=ch&&ch<=‘9‘)&&!(‘A‘<=ch&&ch<=‘Z‘)&&!(‘a‘<=ch&&ch<=‘z‘)); 167 }
这是我做PTA第4章实践1的AI核心代码的时候写的代码,我的想法是一次性输入所有的对话,然后根据要求对输入的对话进行修改,再输出对话。
需要注意的是,
因为题目中 “把原文中所有独立的 I 和 me 换成 you;” 的这个要求会加长字符串的长度,所以要预先给对话的字符数组分配更大的空间。
在实现 “把原文中所有独立的 can you 换成 I can;” 和 “把原文中所有独立的 I 和 me 换成 you;” 的时候,应先实现前者,再实现后者。
然后,因为修改时对话的长度有可能会不停的变,所以要在合适的地方加上结束符‘\0‘ 如ch[k]=‘\0‘;,
其他的根据题目的要求去写代码就好。
三、这段时间,你参考了哪些值得向大家分享的资料?每一项推荐都请说明推荐理由及列出相关链接(或书目名称,具体页码)
https://www.cnblogs.com/chenxiwenruo/p/3546457.html
这是一个有关KMP算法的博客,里面说到了,
“理解next数组的含义:next[i]表示前面长度为i的子串中,前缀和后缀相等的最大长度”。
若按此博客中的理解去想,则 next[i]既是下标、又是最大长度,
而按书中的描述去想,则 next[i]为位置,也为前缀和后缀相等的最大长度+1,
对我来说,前者更容易使人接受、理解。
四、目前学习过程中存在的困难,待解决或待改进的问题
脑子还是太缺筋,将很多简单的问题复杂化了。
还有就是我觉得我对i和j有执念,我觉得i和j的作用域一定要在循环里面/捂脸,导致如果要在循环外用到i或j结束时的值时,我会引入一个k在循环中记录i或j的值。
五、上次博客确定的目标达到了吗?如果没达到,请分析原因
没达到,没有看老师给的高质量c++编程指南31~60页,因为自己做事的效率实在太低,整天都在空思考,重复思考。
六、接下来的目标
看老师给的高质量c++编程指南31~90页。
原文地址:https://www.cnblogs.com/ymj19/p/10695826.html