第四章作业题总结

第四章作业题总结--只谈一些想法

1、串模式匹配

 

7-1 串的模式匹配 (30 分)
 
给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串S中出现的位置。

输入格式:
输入有两行: 第一行是主串S; 第二行是模式T.

输出格式:
输出相匹配的子串中的第一个字符在主串S中出现的位置。若匹配失败,输出0.

输入样例:

在这里给出一组输入。例如:
aaaaaba
ba

输出样例:
在这里给出相应的输出。例如:
6
View Code

 

作者: 陈晓梅
单位: 广东外语外贸大学
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB
 
这道题主要是考我们对KMP算法的一个应用,虽然BF算法也可以,但是再某些数据量特别大的时候,就有点不太适合了,我已经在第四章总结里面写了关于这个算法的一些内容,这个就直接放代码吧。
 
代码如下:
 
#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;
}
View Code

 

关于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、稀疏矩阵

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
View Code
作者: 陈晓梅
单位: 广东外语外贸大学
时间限制: 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的值来判断来输出即可
 
代码(完全自己写的哼唧唧,我好棒)
 (怕被老师“打”还是折叠吧)
#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;
}
View Code

 

 

3、AI之题
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
View Code

 

  

作者: 未知
单位: 未知
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB
 
貌似是某个天梯赛的一道题??我也不懂,反正老师拉过来给我们当作业了
 
但是在老师的引导下,我觉得本题的思考就是:
先把主函数写出来,同时开始弄几个结构,再根据题目给的信息一步一步将接口完善
(PS:一定要注意那个 == 和 = 的区别,改了一下午,就是有个地方不能通过,最后一个个看,发现多了一个 = 最后输出结果总是错的)
 
#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;
}

 
View Code

 

 
我觉得老师写的博客其实就很好了,强推:
https://www.cnblogs.com/cxmCnBlogs/p/10691278.html
 
posted @ 2019-04-14 16:04  青梅茶  阅读(490)  评论(1编辑  收藏  举报