第四章作业题总结--只谈一些想法
1、串模式匹配
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
7-1 串的模式匹配 (30 分) 给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串S中出现的位置。 输入格式: 输入有两行: 第一行是主串S; 第二行是模式T. 输出格式: 输出相匹配的子串中的第一个字符在主串S中出现的位置。若匹配失败,输出0. 输入样例: 在这里给出一组输入。例如: aaaaaba ba 输出样例: 在这里给出相应的输出。例如: 6
作者: 陈晓梅
单位: 广东外语外贸大学
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB
这道题主要是考我们对KMP算法的一个应用,虽然BF算法也可以,但是再某些数据量特别大的时候,就有点不太适合了,我已经在第四章总结里面写了关于这个算法的一些内容,这个就直接放代码吧。
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<string.h> using namespace std; /*这次题目中,既有如题所示的几个小小的字符串 也有测试数据中的 10^5、10^6的大数据,因此需要kmp算法 不过后续会尝试一下BF算法 */ char *jg (string str)//返回一整个函数 { int size = str.length(); char *s; s = new char[size]; strcpy(s,str.c_str());//strcpy是一种C语言的标准库函数,strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char* return s; } void calc_next(string pstring, int *next) {//设计一个函数next,来修正next的数值 next[0] = -1;//表示模式串的开头,为-1,否则会错位 int j = 0, k = -1; int plen = pstring.length();//模式串的长度 char *p = jg(pstring);//模式串的字符数组 while (j < plen) { if(k == -1 || p[j] == p[k]) { k++; j++; next[j] = k;/*next数组存放着已匹配的子串中最长的前后缀, next[j] 表示p[0]-p[j] 子串中最长的前后缀长度*/ } else{ k = next[k]; //k回溯到模式串的开头 } } } int kmp( string s, string pstring) { int *next = new int [pstring.length()]; calc_next(pstring,next);//得到 next[]数组 char *c = jg(s); char *p = jg(pstring); //转换字符串为字符数组 int i=0,j=0; int pos = 0; while( i<=s.length()|| j<=pstring.length() ) { if(j ==-1 || c[i] == p[j]){ i++; j++; } else{ j = next[j];// } /* (1)有着最长前后缀的时候,主串与模式串在主串s[j]的位置(模式串最长后缀后一位) 不匹配的时候の 时候,s[j]将会与模式串的最长前后缀的后一位进行比较 (2)没有最长前后缀的时候,整个模式串后移一位 */ if(j == pstring.length()){//匹配成功 pos = i-j+1; break; } } return pos; } int main() { string s, pstring;//定义字符串 ,模式串 getline(cin, s);//输入字符串 getline(cin, pstring);//输入模式串 cout<<kmp(s, pstring); return 0; }
关于string函数的一些内容:
String 对象是 System Char 对象的有序集合,用于表示字符串。String 对象的值是该有序集合的内容,并且该值是不可变的
String就是C++、JAVA、VB等编程语言中的字符串,用双引号引起来的几个字符.如"Abc","一天".
string的子串:
1
|
string substr(
int
pos = 0,
int
n = npos)
const
;
//返回pos开始的n个字符组成的字符串
|
string的比较:
bool
operator==(
const
string &s1,
const
string &s2)
const
;
//比较两个字符串是否相等 运算符">","<",">=","<=","!="均被重载用于字符串的比较;
int
compare(
const
string &s)
const
;
//比较当前字符串和s的大小
int
compare(
int
pos,
int
n,
const
string &s)
const
;
//比较当前字符串从pos开始的n个字符组成的字符串与s的大小
int
compare(
int
pos,
int
n,
const
string &s,
int
pos2,
int
n2)
const
;
//比较当前字符串从pos开始的n个字符组成的字符串与s中//pos2开始的n2个字符组成的字符串的大小
int
compare(
const
char
*s)
const
;
int
compare(
int
pos,
int
n,
const
char
*s)
const
;
int
compare(
int
pos,
int
n,
const
char
*s,
int
pos2)
const
;
//compare函数在大于(>)时返回1,小于(<)时返回-1,等于(==)时返回0
string的一些函数构造:
string(); string( size_type length, char ch ); string( const char *str ); string( const char *str, size_type length ); string( string &str, size_type index, size_type length ); string( input_iterator start, input_iterator end );
资料来源:
https://baike.baidu.com/item/string/5137266?fr=aladdin
https://www.cnblogs.com/aminxu/p/4686320.html
2、稀疏矩阵
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
7-1 稀疏矩阵 (30 分) 如果一个矩阵中,0元素占据了矩阵的大部分,那么这个矩阵称为“稀疏矩阵”。对于稀疏矩阵,传统的二维数组存储方式,会使用大量的内存来存储0,从而浪费大量内存。为此,可以用三元组的方式来存放一个稀疏矩阵。 对于一个给定的稀疏矩阵,设第r行、第c列值为v,且v不等于0,则这个值可以表示为。这个表示方法就称为三元组。那么,对于一个包含N个非零元素的稀疏矩阵,就可以用一个由N个三元组组成的表来存储了。 如:{<1, 1, 9>, <2, 3, 5>, <10, 20, 3>}就表示这样一个矩阵A:A[1,1]=9,A[2,3]=5,A[10,20]=3。其余元素为0。 要求查找某个非零数据是否在稀疏矩阵中,如果存在则输出其行列下标,不存在则输出ERROR。 输入格式: 共有N+2行输入: 第一行是三个整数m, n, N(N<=500),分别表示稀疏矩阵的行数、列数和矩阵中非零元素的个数,数据之间用空格间隔; 随后N行,输入稀疏矩阵的非零元素所在的行、列值和非零元素的值; 最后一行输入要查询的非0数据k。 输出格式: 如果存在则输出其行列下标,不存在则输出ERROR。 输入样例: 在这里给出一组输入。例如: 10 29 3 2 18 -10 7 1 98 8 10 2 2 输出样例: 在这里给出相应的输出。例如: 8 10
作者: 陈晓梅
单位: 广东外语外贸大学
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB
关于本题的话,我感觉就是在为数学做一个exe
(1)三个整数,m(行)、n(列)、N(个非零元素)
(2)输入:1)m、n、N的值
2)非零元所在的行、列、值
3)最后一行输入的一个数字是需要查找的值
(3)输出:1)输入的数字在改矩阵中则输出行与列
2)不在则输出ERROR
那么首先是输入这三个数,然后扩充数组,然后输入需要查询的数值,最后引入一个flag--最喜欢flag了,用flag的值来判断来输出即可
代码(完全自己写的哼唧唧,我好棒)
(怕被老师“打”还是折叠吧)
View Code
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> using namespace std; int main() { int m,n,N; cin>>m>>n>>N;//行列和个数 N=3*N; int a[N]; for(int i=0;i<N;i++) { cin >> a[i]; }//输入三个元素 int c,flag=0; cin >> c;//输入需要查询的数 int j=2; for(j=2;j<N;j=j+3) { if (c==a[j]) {flag=0; break; } else { flag=1; continue; } }//只与输入的非零元素进行比较 if(flag == 0) cout<<a[j-2]<<" "<<a[j-1]<<endl; else cout<<"ERROR"<<endl;//对,就输出,不对就是ERROR return 0; }
3、AI之题
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
7-2 AI核心代码 (30 分) 本题要求你实现一个简易版的 AI 英文问答程序,规则是: 无论用户说什么,首先把对方说的话在一行中原样打印出来; 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉; 把原文中所有大写英文字母变成小写,除了 I; 把原文中所有独立的 I 和 me 换成 you; 把原文中所有的问号 ? 换成惊叹号 !; 把原文中所有独立的 can you 换成 I can —— 这里“独立”是指被空格或标点符号分隔开的单词; 在一行中输出替换后的句子作为 AI 的回答。 输入格式: 输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。 输出格式: 按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。 输入样例: 在这里给出一组输入。例如: 6 Hello ? Good to chat with you can you speak Chinese? Really? Could you show me 5 What Is this prime? I,don 't know 输出样例: 在这里给出相应的输出。例如: Hello ? AI: hello! Good to chat with you AI: good to chat with you can you speak Chinese? AI: I can speak chinese! Really? AI: really! Could you show me 5 AI: could you show you 5 What Is this prime? I,don 't know AI: what Is this prime! you,don't know
作者: 未知
单位: 未知
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB
貌似是某个天梯赛的一道题??我也不懂,反正老师拉过来给我们当作业了
但是在老师的引导下,我觉得本题的思考就是:
先把主函数写出来,同时开始弄几个结构,再根据题目给的信息一步一步将接口完善
(PS:一定要注意那个 == 和 = 的区别,改了一下午,就是有个地方不能通过,最后一个个看,发现多了一个 = 最后输出结果总是错的)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstring> #include<cstdio> using namespace std; //string s; //char s[1001]; bool isDependent(char ch) {//判断ch是否为分隔字符 ch = tolower(ch); if(ch>='0'&&ch<='9'|| ch>='a'&& ch<='z') return false; else return true; } bool isCanyou(char t[],int j) //判断一个独立的can you { if(t[j]=='c' && t[j+1]=='a' && t[j+2]=='n' && t[j+3]==' ' && t[j+4]=='y' && t[j+5]=='o' && t[j+6]=='u'){ if((j==0 || isDependent(t[j-1]) ) && isDependent(t[j+7])) return true; } else return false; } void go(string s) {//根据s输出 char t[3003];//1000个大I // string t =="";//无初始化,无法保存 //尝试开头的空格删去 int i,j;//i:定位s的第一个非空 for(i=0;s[i] !='\0' && s[i] ==' ';++i);//全部是空格,无边界,因为输入最后的空格改成\0; j = 0; while(s[i]!='\0'){//把s串copy到t,连续的字符“ ”只复制一个 if(s[i]==' ' && s[i-1]==' ') { ++i; continue ; } if(s[i]=='?') { t[j]='!';//改问号为感叹号 i++; j++; continue; } if(s[i]!='I') {t[j] = tolower(s[i]); j++; i++; }//利用tolower else{t[j++] = s[i++]; } } t[j] = '\0'; //把原文中所有独立的 I 和 me 换成 you,所有独立的 can you 换成 I can j=0; while(t[j]!='\0'){ if(t[j]=='I' && (j==0 || isDependent(t[j-1])) && isDependent(t[j+1])){ //I换成you cout<<"you"; ++j; continue; } if(t[j]=='m' && t[j+1]=='e' && (j==0|| isDependent(t[j-1])) && isDependent(t[j+2])) //me换成you { cout << "you"; j=j+2; continue; } if(isCanyou(t,j) && isDependent(t[j-1]) && isDependent(t[j+7])){ //can you换成I can cout << "I can"; j+=7; continue; } if(t[j]==' '&& isDependent(t[j+1])){ ++j; continue; } cout << t[j]; ++j; } cout<<endl; } int main() { int n; string s; cin >> n; getchar();//吸收回车 for(int i=0; i<n; i++) { getline(cin,s); cout << s << endl; cout << "AI: " ; go(s);//根据s(作为参数要传给go函数) 输出AI回答 } return 0; }
我觉得老师写的博客其实就很好了,强推:
https://www.cnblogs.com/cxmCnBlogs/p/10691278.html