头歌的编程题,仅供参考
第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;
}

2984

被折叠的 条评论
为什么被折叠?



