头歌编程题实训-串

该文章已生成可运行项目,

头歌的编程题,仅供参考 

第1关:基于BF算法的病毒感染监测

#include<iostream>
#include<cstring>
#define MAXSIZE 1000
using namespace std;
int BF(char a[],char b[])
{//简单模式匹配算法,匹配成功返回1,否则返回0
/**************begin************/
    int i = 0,flag = 0,tem;
    for(;a[i]!='\0';i++){
        int tem = i,j = 0;//每次比较不匹配后i才能++,但每比完一个字符若正确要比较下一个
        for(;b[j]!='\0';j++,tem++){
            if(a[tem]!=b[j]) {
                break;
            }
        }
        if(b[j]=='\0') {
            flag = 1;//在如果不匹配,主串就右移,子串就从头比较的情况下,只有子串全部匹配,子串才能遍历到最后的'\0'
            break;
        }
    }
    return flag;
    /**************end************/
}
void Revolve(char a[])
{//字符串旋转,把病毒第一个字符变为最后一个字符
/**************begin************/
    char tem = a[0];
    int i = 1;
    for(;a[i]!='\0';i++){
        a[i-1] = a[i];
    }
    a[i-1] = tem;
    /**************end************/
}
int Judge(char b[],char a[])//和BF的形参有些许不同
{//判别病毒DNA环状序列是否在患者DNA序列中出现过,出现过返回1,否则返回0
/**************begin************/
int revolTimes = 0,flagJudge = 0;//flag被BF占了
while(b[revolTimes]!='\0') revolTimes++;//求环形病毒可revolve次数
for(int i=0;i<revolTimes;){
    int flag = BF(a,b);
    if(flag==0){
        Revolve(b);
        i++;
    }
    else {
        flagJudge = 1;
        break;
    }
}
return flagJudge;
    /**************end************/
}
int main()
{
	char a[MAXSIZE],b[MAXSIZE];//a存入病毒的DNA序列,b存入人的DNA序列
	while(cin>>a>>b)
	{
	    if(strcmp(a,"0")==0&&strcmp(b,"0")==0)
            break;
        int result=Judge(a,b);//即便Judge没有返回1或0,result仍有未知的残留值,所以初始代码也能打印出YES
        if(result)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
 	}
	return 0;
}

第2关:基于BF算法的网络入侵检测

#include<iostream>
#include<cstring>
#include<sstream>
using namespace std;
int BF(string s,string t)
{//简单模式匹配算法,S为主串(目标串),T为子串(模式串)。
//匹配成功返回主串中所含子串第一次出现的位置,否则返回-1。
/**************begin************/
    int i = 0, j = 0;  
    while (i<s.length()&&j<t.length()){  
        if (s[i]==t[j]){  
            i++;  
            j++;  
        } 
        else{  
            i = i-j+1;  
            j = 0;  
        }
        if (j>=t.length()) return i-j;   
    }   
    return -1;  
    /**************end************/
}
int main()
{
    int n,m;
    while (cin>>n>>m)//输入n条规则,并将其中的n个ip地址存放到ip数组,输入m条日志,并合并存放到log
    {
        cin.get();     
        string *rule=new string[n];  
        string log="";
        for(int i=0;i<n;i++)
        {
            string t;
            getline(cin,t);
            stringstream sss(t);   
            string pot,ip,msg;
            sss>>pot>>ip;
            rule[i]=ip.substr(3, ip.length() - 3);
        }
        for(int i=0;i<m;i++)
        {
            string t;
            getline(cin,t);
            log += t;
        }
        for(int i=0;i<n;i++)
        {
            if(BF(log,rule[i])!=-1)
            {
                cout<<"Intrusion."<<endl;
                return 0;
            }
        }
        cout<<"No Intrusion."<<endl;
		delete[] rule;	
        return 0;
    }
}

第3关:基于KMP算法的网络入侵检测

#include<iostream>
#include<cstring>
#include<sstream>
using namespace std;
void GetNext(string pattern,int* next)
{//每个模式的下一个输出值 和 下一个输入数字组
	int j=0, k=-1;
	next[j]=k;
	while (j<(int)pattern.length()-1){
		if(k==-1||pattern[j]==pattern[k]){
			j++;
			k++;
			next[j]=k;
		}
		else{
			k=next[k];
		}
	}
}
int KMP(string target,string pattern,int* next)
{//KMP匹配算法,target为主串,pattern为子串。
//匹配成功返回主串中所含子串第一次出现的位置,否则返回-1。
//调用GetNext函数获取模式串的next数组
/**************begin************/
    GetNext(pattern,next);        //设置模式中的下一个数字组    
    int i = 0, j = 0;
    while (i<(int)target.length()&&j<(int)pattern.length()){
        if(j==-1||target[i]==pattern[j]) {    
            i++;
            j++;
        }
        else {        //模式方向正确
            j = next[j];
        }
    }
    if(j==pattern.length())
        return i-j;    //已成功匹配
    return -1;    //不匹配
    /**************end************/
}
int main()
{
    int n,m;
    while (cin>>n>>m)
    {
        cin.get();     //将接收第一个返回,并阻止对netline()的输入
        string *rule=new string[n];   //规则编号组存储ip地址
        string log="";
        for(int i=0;i<n;i++)
        {
            string t;
            getline(cin,t);
            stringstream sss(t);   //根据规范将字段左侧分成一个字符
            string pot,ip,msg;
            sss>>pot>>ip;
            rule[i]=ip.substr(3, ip.length() - 3);
        }
        for(int i=0;i<m;i++)
        {
            string t;
            getline(cin,t);
            log += t;
        }
        for(int i=0;i<n;i++)
        {
            int *next=new int[rule[i].length()];
            if(KMP(log,rule[i],next)!=-1)
            {
                cout<<"Intrusion."<<endl;
                return 0;
            }
            delete[] next;	//删除组指针空间
        }
        cout<<"No Intrusion."<<endl;
		delete[] rule;
        return 0;
    }
}

第4关:基于BM算法的网络入侵检测

#include<iostream>
#include<cstring>
#include<sstream>
#include<algorithm>
using namespace std;
int* getBc(const string & pattern)
{//得到坏字符bc数组
    int *bc=new int[256];
    int len=pattern.length();
    for (int i=0; i<256;++i)
        bc[i]=-1;
    for (int i=0; i<len;++i)
    {
        bc[pattern[i]]=i;
    }
    return bc;
}
int* suffixes(const string & pat)
{
    const int len=pat.length();
    int num;
    int *suff=new int[len];
    suff[len-1]=len;
    for (int i=len-2;i>=0;--i)
    {
        for (num=0;num<=i&&pat[i-num]==pat[len-num-1];++num);
  
        suff[i]=num;
    }
    return suff;
}
int* getGs(const string & pat)
{
    const int len=pat.length();
    const int lastIndex=len-1;
    int *suffix=suffixes(pat);
    int *gs=new int[len];
    for(int i=0;i<len;++i)
        gs[i]=len;
    
    for(int i=lastIndex;i>= 0;--i)
    {
        
        if(suffix[i]==i+1)
        {
            for(int j=0;j<lastIndex-i;++j)
            {
                if(gs[j]==len)
                    gs[j]=lastIndex-i;
            }
        }
    }
  
    for(int i=0;i<lastIndex;++i)
    {
        gs[lastIndex-suffix[i]]=lastIndex-i;
    }
    delete[] suffix;
    return gs;
}
int BM(const string & text, const string & pat)
{//在str.ch中匹配pattern.ch,匹配成功返回主串中所含子串第一次出现的位置,否则返回-1。
//分别求坏字符数组bc和好字符数组suffix、prefix,分别计算两个策略的移动位数,取大值作为最终移动位数
    /**************begin************/
    int *bc = getBc(pat);
    int *gs = getGs(pat);
    int patAt = 0;  //PatAt是指当前PatAt和代码文本对齐的位置
    int cmp;  //Cmp指当前偏移的位置
    const size_t PATLASTID = pat.length()-1;
    const size_t patLen = pat.length();
    const size_t textLen = text.length();
    while(patAt+patLen<=textLen){
        //如果区域匹配成功,Lamp会将细条延伸到-1的位置
        //patAt + cmp 指序列文本中当前位置的字符
        for (cmp=PATLASTID;cmp>=0&&pat[cmp]==text[patAt+cmp];--cmp);
        if (cmp==-1) break;
        else{
            patAt += max(gs[cmp],cmp-bc[text[patAt+cmp]]);
        }
    }
    delete[] bc;
    delete[] gs;
    return (patAt+patLen<=textLen)?patAt:-1;
}
int main()
{
    int n,m;
    while (cin>>n>>m)
    {
        cin.get();     //将接收第一个返回,并阻止对netline()的输入
        string *rule=new string[n];   //规则编号组存储ip地址
        string log="";       //log保存并接收
        for(int i=0;i<n;i++)
        {
            string t;
            getline(cin,t);
            stringstream sss(t);   //根据规范将字段左侧分成一个字符
            string pot,ip,msg;
            sss>>pot>>ip;
            rule[i]=ip.substr(3, ip.length() - 3);
        }
        for(int i=0;i<m;i++)
        {
            string t;
            getline(cin,t);
            log += t;
        }
        for(int i=0;i<n;i++){
            if(BM(log,rule[i])!=-1)
            {
                cout<<"Intrusion."<<endl;
                return 0;
            }
        }
        cout<<"No Intrusion."<<endl;
        delete[] rule;    //删除组指针空间
        return 0;
    }
}

第5关:统计字符出现的频度

#include<iostream>
#include<cstring>
using namespace std;
void Count(string c,int b[])
{//统计字符出现的频度
/**************begin************/  
    for (int i=0;i<c.length();i++){    
        if(c[i]>='0'&&c[i]<='9') b[c[i]-'0']++;  
        else b[c[i]-'A'+10]++;    
    }       
    for (int i=0;i<36;i++){    
        if (b[i]>0){  // 如果频度大于0,则输出  
            if(i>=0&&i<=9) cout<<i<<":"<<b[i]<<endl; // 数字  
            else cout<<(char)(i-10+'A')<<":"<<b[i]<<endl; // 大写字母  
        }  
    }
        /**************end************/
}
int main()
{
    string c;     //存储输入的字符串
    while(cin>>c)
    {
        if(c=="0") break;
        int *b=new int[36]{0};        	//存储对应字符的个数
        Count(c,b);
    }
    return 0;
}

第6关:递归实现字符串的逆序存储

#include<iostream>
#include<cstring>
#define MAXSIZE 100
using namespace std;
void Reverse(char *a,int n)
{//递归实现字符串的逆序存储
/**************begin************/
    if (n <= 0) return;
    char temp = a[0];
    a[0] = a[n-1];
    a[n-1] = temp;
    Reverse(a+1,n-2);
    /**************end************/
}
int main()
{
	char a[MAXSIZE];
	while(cin>>a)
	{
		if(strcmp(a,"0")==0) break;
		int i=0;
		while(a[i]!='\0') i++;  //统计字符数
		Reverse(a,i);
		cout<<a<<endl;  //输出字符数组
	}
	return 0;
}

第7关:字符串的插入

#include<iostream>
#define MAXSIZE 100
using namespace std;
void Insert(char s[],char t[],int pos,int LenS,int LenT)
{//字符串的插入
    int i;
    for(i=LenS-1;i>=pos-1;i--)     //字符串s的末尾先后移,记得补充接刚来
        s[i+LenT] = s[i];
    for(i=pos-1;i<pos-1+LenT;i++)
        s[i] = t[i-pos+1];           //再将字符串b填入
    LenS += LenT;                 //更新字符串s的长度
    s[LenS] = '\0';                  //字符串的末尾设置为结束符'\0'
    cout<<s<<endl;              //输出字符数组
}
int main()
{
    int pos;
    while(cin>>pos)               //输入插入位置pos
    {
        if(pos<=0) break;
        char s[MAXSIZE],t[MAXSIZE];
        cin>>s>>t;                   //输入字符串s和t
        int LenS=0,LenT=0;
        while(s[LenS]!='\0') LenS++;           //求字符串s的长度LenS
        while(t[LenT]!='\0') LenT++;          //求字符串t的长度LenT
        if(pos>LenS) break;       //插入位置非法
        Insert(s,t,pos,LenS,LenT);
    }
    return 0;
}

第8关:查找子串第一次出现的位置

#include<iostream>
#include<string.h>
using namespace std;
int strstr(string s1,string s2)
{//查找子串第一次出现的位置
/**************begin************/  
    int len1 = s1.length();
    int len2 = s2.length();
    for(int i=0;i<=len1-len2;i++){
        int j;
        for (j=0;j<len2;j++){
            if (s1[i+j]!=s2[j]){
                break;
            }
        }
        if (j==len2){
            return i;  
        }
    }
    return -1;
    /**************end************/
}
int main()
{
	string s1, s2;
	while(cin>>s1>>s2)
	{
	    if (s1=="0"&&s2=="0") break;
        int pos=strstr(s1,s2);
        cout<<pos<<endl;
	}
	return 0;
}

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值