算法入门系列之字符串
1.26
UVA10010
好想说这道题我做了好久~快哭了~最后还是利用了udebug那个网站,才找到了bug
这道题收获很大对于我这个代码能力不强的人,基础知识不牢的人来说多练练还是有好处的~
1.思路:这道题给定一个二维数组,然后给你多个字符串,问你这些字符串在这个二维数组中是否能找到,重点是:方向有八个:向上,向下,向左,向右,左上,左下,右上,右下。所以读懂题意非常重要!
2.一个很重要的bug就是想说
while(str[x++][y]==test[t++]); while(a++==b++);
上面这两句代码不一样:
第一行的意思是,先x++,t++,再比较;
第二行的意思是先判断ab是否相等,a++,b++;
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 int m,n,T; 6 char str[55][55]; 7 char test[55]; 8 int len; 9 int call(int x,int y,int len){ 10 //向左 11 if(x+1-len>=0){ 12 //printf("1...........\n"); 13 int i=x,j=y; 14 int t=0; 15 // printf("%c %c",str[i][j],test[t]); 16 while(t<len&&str[i][j]==test[t]){ 17 i--;t++; 18 } 19 // printf("%d\\\\\t",t); 20 if(t==len)return 1; 21 22 } 23 //向右 24 if(m-x>=len){ 25 //printf("2...........\n"); 26 int i=x,j=y; 27 int t=0; 28 while(str[i][j]==test[t]&&t<len){ 29 i++; 30 t++; 31 } 32 if(t==len)return 1; 33 } 34 //向上 35 if(y+1-len>=0){ 36 //printf("3...........\n"); 37 int i=x,j=y; 38 int t=0; 39 while(str[i][j]==test[t]&&t<len){ 40 j--; 41 t++; 42 } 43 if(t==len)return 1; 44 } 45 //向下 46 if(n-y>=len){ 47 //printf("4...........\n"); 48 int i=x,j=y; 49 int t=0; 50 while(str[i][j]==test[t]&&t<len){ 51 j++;t++; 52 } 53 if(t==len)return 1; 54 } 55 //左上-+ 56 if(x+1-len>=0&&n-y>=len){ 57 // printf("5...........\n"); 58 int i=x,j=y; 59 int t=0; 60 while(str[i][j]==test[t]&&t<len){ 61 i--;j++;t++; 62 } 63 if(t==len)return 1; 64 } 65 //右上+- 66 if(m-x>=len&&y+1-len>=0){ 67 //printf("6...........\n"); 68 int i=x,j=y; 69 int t=0; 70 while(str[i][j]==test[t]&&t<len){ 71 i++;j--;t++; 72 } 73 if(t==len)return 1; 74 } 75 //左下-- 76 if(y+1-len>=0&&x+1-len>=0){ 77 //printf("7...........\n"); 78 int i=x,j=y; 79 int t=0; 80 while(str[i][j]==test[t]&&t<len){ 81 i--;j--;t++; 82 } 83 if(t==len)return 1; 84 } 85 //右下++ 86 if(n-y>=len&&m-x>=len){ 87 //printf("8...........\n"); 88 int i=x,j=y; 89 int t=0; 90 while(str[i][j]==test[t]&&t<len){ 91 i++;j++;t++; 92 } 93 if(t==len)return 1; 94 } 95 return 0; 96 } 97 int main(){ 98 //freopen("10010.txt","r",stdin); 99 //freopen("10011.txt","w",stdout); 100 int z; 101 scanf("%d",&T); 102 while(T--){ 103 getchar(); 104 scanf("%d%d",&m,&n); 105 for(int i=0;i<m;i++){ 106 scanf("%s",&str[i]); 107 } 108 for(int x=0;x<m;x++){ 109 for(int y=0;y<n;y++){ 110 if(str[x][y]>='A'&&str[x][y]<='Z'){ 111 str[x][y]+=32; 112 } 113 } 114 } 115 scanf("%d",&z); 116 while(z--){ 117 scanf("%s",test); 118 int len=strlen(test); 119 for(int i=0;i<len;i++){ 120 if(test[i]>='A'&&test[i]<='Z'){ 121 test[i]+=32; 122 //printf("%c ",test[i]); 123 } 124 } 125 int p=0; 126 for(int x=0;x<m;x++){ 127 for(int y=0;y<n;y++){ 128 if(str[x][y]==test[0]){ 129 if(call(x,y,len)){ 130 printf("%d %d\n",x+1,y+1); 131 p=1; 132 break; 133 } 134 } 135 136 } 137 if(p)break; 138 } 139 } 140 if(T!=0)printf("\n"); 141 } 142 return 0; 143 }
UVA10361
这道题真的是很折腾人啊~
一句话,不能轻视水题~虽然这题一点都不水~
1.题意:很简单的s1<s2>s3<s4>s5;第一个行的字符串把左右括号去掉输出,第二行把...变成s3<s2><s1><s4>输出即可;
2.思路:还是用最简单的一个一个字符查找,通过将上面的后四个字符存到四个数组中,然后按照输出要求的顺序输出。
3.我错的一个重要的地方就是两个gets函数中间使用了getchar,本意是为了过滤掉回车的,然而百度之后,得知,gets函数是读到回车结束,但是回车不存入数组中!!!!
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int main(){ char l1[105],l2[105]; char a[5][105]; int T; // freopen("10010.txt","r",stdin); // freopen("10011.txt","w",stdout); scanf("%d",&T); getchar(); while(T--){ gets(l1); //getchar(); gets(l2); // printf("%s %s",l1,l2); int w=0; int len=strlen(l1); int k=0; while(k<len){ if(l1[k]=='<'){ k++; int i; i=0; while(l1[k]!='>'){ a[w][i++]=l1[k]; k++; } a[w][i++]='\0'; w++; k++; i=0; while(l1[k]!='<'){ a[w][i++]=l1[k]; k++; } k++; a[w][i++]='\0'; w++; i=0; while(l1[k]!='>'){ a[w][i++]=l1[k]; k++; } a[w][i++]='\0'; w++; i=0; k++; while(i<len){ a[w][i++]=l1[k]; k++; } a[w][i++]='\0'; }else k++; } /* for(int i=0;i<=w;i++){ printf("%s\n",a[i]); }*/ int num=0; while(num<len){ if(l1[num]!='<'&&l1[num]!='>'){ printf("%c",l1[num]); } num++; } printf("\n"); int num1=0; int lens=strlen(l2); while(num1<lens){ if(l2[num1]=='.'){ printf("%s%s%s%s",a[2],a[1],a[0],a[3]); break; } printf("%c",l2[num1]); num1++; } printf("\n"); } return 0; }
1.27
UVA537
这道题纯暴力写的
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> using namespace std; int flag1,flag2,flag3; double P,U,I; char a[200]; char str[200]; int k,les; void cal(int len){ int i=0; flag1=0;flag2=0;flag3=0; while(i<len){ if(a[i]=='='){ if(a[i-1]=='P'){ k=0; les=0; while(i<len){ i++; str[k]=a[i]; k++; if(a[i+1]=='m'){ i++; les=1; }else if(a[i+1]=='k'){ i++; les=2; }else if(a[i+1]=='M'){ i++; les=3; } if(a[i+1]=='W'){ i++; break; } } str[k]='\0'; P=atof(str); if(les==1) P*=0.001; else if(les==2) P*=1000; else if(les==3) P*=1000000; // printf("%s %lf\n",str,P); flag1=1; }else if(a[i-1]=='U'){ k=0; les=0; while(i<len){ i++; str[k]=a[i]; k++; if(a[i+1]=='m'){ i++; les=1; }else if(a[i+1]=='k'){ i++; les=2; }else if(a[i+1]=='M'){ i++; les=3; } if(a[i+1]=='V'){ i++; break; } } str[k]='\0'; U=atof(str); if(les==1) U*=0.001; else if(les==2) U*=1000; else if(les==3) U*=1000000; // printf("%s %lf\n",str,U); flag2=1; }else if(a[i-1]=='I'){ k=0; les=0; while(i<len){ i++; str[k]=a[i]; k++; if(a[i+1]=='m'){ i++; les=1; }else if(a[i+1]=='k'){ i++; les=2; }else if(a[i+1]=='M'){ i++; les=3; } if(a[i+1]=='A'){ break; } } str[k]='\0'; I=atof(str); if(les==1) I*=0.001; else if(les==2)I*=1000; else if(les==3)I*=1000000; //printf("%s %lf\n",str,I); flag3=1; } } i++; } if(flag1&&flag2){ printf("I=%.2lfA\n",P/U); }else if(flag1&&flag3){ printf("U=%.2lfV\n",P/I); }else if(flag2&&flag3){ printf("P=%.2lfW\n",U*I); } } int main(){ int T; freopen("in.txt","r",stdin); scanf("%d",&T); getchar(); for(int num=0;num<T;num++){ gets(a); int len=strlen(a); printf("Problem #%d\n",num+1); cal(len); printf("\n"); } return 0; }
UVA10815
这道题需要注意的是字符数组排序!
字符数组排序,如果使用sort的话,记住,cmp比较函数:bool cmp(char *a,char *b) 传入的参数是指针类型,所以传入的不能是字符数组,而应该是字符类型的指针!!
因此如果使用sort不能用二维数组,而使用的是指针数组,即数组里面存的是字符类型指针!所以最开始读入之后要把内容赋给指针!
因此sort的写法是sort(&strc[0],&strc[0]+num,cmp);或sort(strc,strc+num,cmp);
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 char a[1000005][205]; 7 char *strc[1000005];//指针数组(由指针组成的数组) 8 char str[205]; 9 bool cmp(char *a,char *b){ 10 if(strcmp(a,b)<0){ 11 return true; 12 }return false; 13 14 } 15 int main(){ 16 freopen("in.txt","r",stdin); 17 int num=0; 18 int len; 19 int i; 20 while(scanf("%s",str)!=EOF){ 21 // printf("%s",str); 22 len=strlen(str); 23 i=0; 24 int k=0; 25 int flag; 26 while(i<len){ 27 flag=0; 28 // printf("?"); 29 k=0; 30 while((str[i]<='Z'&&str[i]>='A') 31 ||(str[i]<='z'&&str[i]>='a')){ 32 // printf("%c ",str[i]); 33 a[num][k]=tolower(str[i]); 34 // printf("%c ",str[i]); 35 i++; 36 k++; 37 flag=1; 38 } 39 if(flag==1){ 40 a[num][k]='\0'; 41 num++; 42 } 43 i++; 44 //printf("%s",a[num]); 45 } 46 } 47 for(int i=0;i<num;i++){ 48 strc[i]=a[i]; 49 } 50 sort(&strc[0],&strc[0]+num,cmp); 51 printf("%s\n",strc[0]); 52 for(int i=1;i<num;i++){ 53 if(strcmp(strc[i-1],strc[i])==0)continue; 54 printf("%s\n",strc[i]); 55 } 56 return 0; 57 }
1.28
UVA10115
这道题学会了strstr函数,strcpy,stract的用法!
首先 观察下列函数。
//用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。 char *strstr(char *str1, const char *str2); //把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间。 char *strcpy(char* dest, const char *src); //把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')。 char *strcat(char *dest,char *src);
strstr函数可以用于查找句子中是否有对应的单词,其返回的是指针所指向的位置。
传入的是指针,即利用strcpy我们可以将目的字符串复制到任意指针指向位置!
利用strcat我们可以在字符串后面添加指针指向的任意位置后面的所有字符!这是指针的妙处所在!
本题的难点在于:如何替换字符,巧妙的方法是,将找到的目的字符串的位置
如上图可知,先把4赋值到str2中,然后吧str2拼接2,然后1拼接str2.
#include<cstring> #include<cstdio> #include<string> #include<iostream> using namespace std; int main(){ char a[100][100],b[100][100],str1[1000],str2[1000]; int n; while(scanf("%d",&n)!=EOF&&n!=0){ getchar(); for(int i=0;i<n;i++){ gets(a[i]); gets(b[i]); } gets(str1); for(int i=0;i<n;i++){ char *p,*q; while(p=strstr(str1,a[i]),p!=NULL){ q=p+strlen(a[i]);//指针指向匹配上的字符串的末尾位置 strcpy(str2,b[i]);//b[i]赋值给str2 strcat(str2,q);//str2后连接q指向位置之后的字符串 strcpy(p,str2);//str2赋值给p指向的起始位置 } } printf("%s\n",str1); } return 0; }
UVA409
这道题写的时间很长,快一个上午,最后还是看的别人的代码,发现自己应该换个思路。
1.题意:输入m个单词,n句话,在n句话中分别记录,每句话中有多少个单词在m中,重点是注意(1)n句话中找到的必须是一个独立的单词,即单词前后不能有字母!
(2)其次注意一句话中有多个相同的单词,同样计数。输出这些话中存在单词最多的话。(3)每个例子之后要输出一个空行!(4)字母部分大小写!
2.思路:我一开始想的是使用strstr函数直接查找位置,然后替换,但是无法很好地解决上(2),所以选择的思路是把每句话中的词都提取出来,然后比较。
3.输入注意:scanf函数不会读'\n',所以如果下面要使用gets的话要加一句getchar,gets函数会读\n,但是不会把\n写到数组里!
#include<cstdio> #include<cstring> #include<iostream> using namespace std; //换个思路!! char a[25][1000],b[25][1000],temp[1000]; int c[1000]; int m,n; bool cmps(char temp[]){ for(int i=0;i<m;i++){ if(strcmp(temp,a[i])==0){ return true; } } return false; } int main(){ int num=0; while(scanf("%d%d",&m,&n)!=EOF){ memset(c,0,sizeof(c)); num++; getchar(); for(int i=0;i<m;i++){ gets(a[i]); int lens=strlen(a[i]); for(int j=0;j<lens;j++){ a[i][j]=tolower(a[i][j]); } } int Max=0; for(int i=0;i<n;i++){ gets(b[i]); int len=strlen(b[i]); int ls=0; while(ls<len){ int k=0; if(isalpha(b[i][ls])){ while(isalpha(b[i][ls])){ temp[k]=tolower(b[i][ls]); k++; ls++; } temp[k]='\0'; if(cmps(temp)) c[i]++; }else { ls++; } } if(Max<c[i]) Max=c[i]; } cout<<"Excuse Set #"<<num<<endl; for(int i=0;i<n;i++){ if(c[i]==Max){ cout<<b[i]<<endl; } } cout<<endl; } return 0; }
UVA10878
这道题注意的是看得出来磁带每行代表字母assic的二进制数即可。还有不要把所有字符都读入再输出结果,因为行数位置。边读入边翻译就好~
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int main(){ char str[15]; int i=0; int flag; flag=1; freopen("in.txt","r",stdin); gets(str); while(gets(str)&&str[0]!='_'){ int sum=0; for(int y=1;y<=5;y++){ if(str[y]=='o'){ sum+=(1<<(8-y)); } } for(int y=7;y<=9;y++){ if(str[y]=='o'){ sum+=(1<<(9-y)); } } printf("%c",sum); } return 0; }
UVA644
这道题注意如果判断是否有一个字符包括另一个字符,那么直接判断短字符是否在长字符里即可~
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; char s[100][100]; char str[1000]; int main(){ int num=0; int i; i=0; while(scanf("%s",str)!=EOF){ if(str[0]!='9'){ strcpy(s[i],str); i++; continue; }else { num++; } //cout<<"/////"<<i<<endl; int flag=0; for(int j=0;j<i;j++){ for(int k=0;k<j;k++){ int l1=strlen(s[j]); int l2=strlen(s[k]); int Max=min(l1,l2); int z=0; while(z<Max){ if(s[j][z]==s[k][z]){ z++; if(z==Max)flag=1; }else { break; } } if(flag)break; } if(flag)break; } if(!flag) cout<<"Set "<<num<<" is immediately decodable"<<endl; else cout<<"Set "<<num<<" is not immediately decodable"<<endl; i=0; } return 0; }
——————————————————————————————————————————————————————————
意识到大学没有多长时间可以再搞ACM了,所以我想按照日记的形式记录我最后的ACM学习生涯~加油!坚持!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步