字符串算法(上)

        文章分上下两章,上是一些字符串相关的基础题,下会包括一些算法

1.字符串中是否有两两重复的元素,例如aabfc就有重复元素a

        题目分析:改题目字符用ASCII表示,那么就可以用计数排序思想,转相应下标

//ti5-1-1
//字符串是否有重复元素,例如aabcdf就有重复的a字符 
//用计数的思想,字符串转下标
#include<stdio.h>
#include<string.h>
bool jishu(char str[]);
void sort(char str[],int begin,int end);
int main(void)
{
	char buf1[100];
	scanf("%s",buf1);
	if(jishu(buf1))
		printf("字符串wuwuwuww重复元素\n");
	else
		printf("字符串有重复元素\n");
	
	return 0;
 } 
 bool jishu(char str[])
 {
 	int buf[26]={0};
 	for(int i=0;i<strlen(str);i++)
 	{
 		if(buf[str[i]-'a']==1)
		 	return false;
		else
			buf[str[i]-'a']++; 
	 }
	 return true;
 }

2.字符串翻转,在不开辟新的存储空间

题目分析:快速排序思想中前后双指针进行字符串的交换

//ti5-1-2
//字符串翻转,在不开辟新的空间下
#include<stdio.h>
#include<string.h>
int main(void)
{
	char buf[100];
	scanf("%s",buf);
	int i=0;
	int j=strlen(buf)-1;
	while(i<j)
	{
		char a=buf[i];
		buf[i]=buf[j];
		buf[j]=a;
		i++;
		j--;
	}
	printf("%s",buf);
	return 0;
 } 

3.是否为变形词,元素种类个数相同的字符串

题目分析:

法一:可以利用计数排序的思路,一个字符串计数时加加,一个字符串计数时减减,最后检查开辟的空间所有元素是否为0

法二:可以对字符串进行排序,然后在进行字符串的比较。

//ti5-1-3
//判断是否为变形词,元素个数和种类都相同,abcd,abdc 
//法一:用计数的思想,字符串转下标
//法二:将两个字符串排序后进行比较 
#include<stdio.h>
#include<string.h>
bool jishu(char str1[],char str2[]);
void sort(char str[],int begin,int end);
int main(void)
{
	char buf1[100];
	char buf2[100];
	scanf("%s %s",buf1,buf2);
	//法一 
//	if(jishu(buf1,buf2))
//		printf("两个字符串相等\n");
//	else
//		printf("两个字符串bububu相等\n");
	//法二
	 sort(buf1,0,strlen(buf1)-1);
	  sort(buf2,0,strlen(buf2)-1);
	 if(strcmp(buf1,buf2)==0)
		printf("两个字符串相等\n");
	else
		printf("两个字符串bububu相等\n");
	return 0;
 } 
 bool jishu(char str1[],char str2[])
 {
 	int buf[26]={0};
 	for(int i=0;i<strlen(str1);i++)
 	{
 		buf[str1[i]-'a']++;
	 }
	 for(int i=0;i<strlen(str2);i++)
	 {
	 	buf[str2[i]-'a']--;
	 }
	 for(int i=0;i<26;i++)
	 {
	 	if(buf[i]!=0)
	 	{
	 		return false;
		 }
	 }
	 return true;
 }
 void sort(char str[],int begin,int end)
 {
 	if(begin>end)
 		return ;
 	int i=begin;
 	int j=end;
 	int base=begin;
 	
	while(i!=j)
	{
	 	while(i<j&&str[j]>=str[base])
 			j--;
 		while(i<j&&str[i]<=str[base])
 			i++;
 		if(i<j)
 		{
 			char a=str[i];
 			str[i]=str[j];
 			str[j]=a;
		 }
	}
 	char a=str[base];
 	str[base]=str[i];
 	str[i]=a;
 	sort(str,begin,i-1);
 	sort(str,i+1,end);
 }

4.将字符串中的空格字符转化为%20

题目分析:遇到空格字符就把字符串空格之后的往后挪动,然后将%20依次赋值上去

//ti5-1-4
//将字符串中空格替换为%20
#include<stdio.h>
#include<string.h>
int main(void)
{
	char buf[100];
	gets(buf);
	for(int i=0;i<strlen(buf);i++)
	{
		int j=strlen(buf)-1;
		while(buf[i]==' ')
		{
			int k=j+2;
			while(i<j)
			{
				buf[k]=buf[j];
				j--;
				k--;
			}
			buf[i++]='%';
			buf[i++]='2';
			buf[i]='0';
		}
	}
	printf("%s",buf);
	return 0;
 } 

5.压缩字符串,若压缩后的字符串大于原字符串,那么输出原字符串,例如aaabbbc压缩后a3b3c1

题目分析:设置标志位,遇到不同的元素,切换标志位

//压缩字符串
#include<stdio.h>
#include<string.h>
int main(void)
{
	char buf[100];
	char str[100];
	gets(buf);
	char count='1';
	int sum=0;
	char log=buf[0];
	for(int i=1;i<strlen(buf);i++)
	{
		if(buf[i]==log)
			count++;	
		if(buf[i]!=log)
		{
			str[sum++]=log;
			str[sum++]=count;
			log=buf[i];
			count='1';			
		}
	}
	str[sum++]=log;
	str[sum++]=count;
	if(strlen(str)>strlen(buf))
		puts(buf);
	else
		puts(str);
	return 0;
 } 
 

6.判断两个字符串的字符集是否相同

题目分析:采用计数排序思想,开辟两个空间对字符进行计数,然后再比较开辟的两个空间的所有元素。

//判断两个字符的字符串是否相同字符集是否相同
//两个字符串开辟两个空间分别进行计数 
#include<stdio.h>
#include<string.h>
int main(void)
{
	char buf1[]="aabcdeedff";
	char buf2[]="abcdefg";
	int str[26]={0};
	int str0[26]={0};
	for(int i=0;i<strlen(buf1);i++)
	{
		if(str[buf1[i]-'a']==0)
			str[buf1[i]-'a']++;
	}
	for(int i=0;i<strlen(buf2);i++)
	{
		if(str0[buf2[i]-'a']==0)
			str0[buf2[i]-'a']++; 
	}
	for(int i=0;i<26;i++)
	{
		if(str[i]!=str0[i])
		{
			printf("两个字符串的字符集bbbbbu相同\n");
			return 0;
		}	
	 } 
	 printf("两个字符串的字符集xxxxiang相同\n");
	return 0;
 } 

7.旋转词,字符串str0通过旋转,能否包含字符串str1

题目分析:有一个重要的点就是,若将str0的字符串使用str0+str0拼接起来,这个字符串将包括str0的所有旋转词,只需要检测str1是否含与str0str0就能判断str0是否可以通过旋转包含str1

//旋转词
//字符串str1翻转是否可以包含字符串str2
//重要思路,字符串str1+str1可以包含所有的旋转词,那么只需要查str2是否包含在内
#include<stdio.h>
#include<string.h> 
int main(void)
{
	char str0[100];//是保存str1+str1的 
	char str1[]="qwertyu";
	char str2[]="rtqwx";
	sprintf(str0,"%s%s",str1,str1);
	for(int i=0;i<strlen(str0);i++)
	{
		if(str0[i]==str2[0])
		{
			int count=0;
			for(int j=i;j<i+strlen(str2)&&(i+strlen(str2)-1<strlen(str0));j++,count++)
			{
				if(str2[count]!=str0[j])
					break;
				if(count==strlen(str2)-1)
				{
					printf("旋转能够包含字符串\n");
					return 0;
				}
			}
		}
	 } 
	 printf("旋转不能包含到\n"); 
	return 0;
}

8.将字符串按照单词翻转 例如 hi good morning,按照单词翻转morning good hi

题目分析:可以先进行字符翻转,这样一个逆序的单词就会交换位置,然后在进行单词内部调序,

//将字符串按单词翻转
//先按照字符翻转
//饭后在一个一个单次的翻转
#include<stdio.h>
#include<string.h>
int main(void)
{
	char buf[100];
	gets(buf);
	int count;//记录空格位置 
	//按照字符翻转 
	for(int i=0,j=strlen(buf)-1;i<j;i++,j--)
	{
		int a=buf[i];
		buf[i]=buf[j];
		buf[j]=a;
	}
	for(int i=0;i<strlen(buf);i++)
	{
		int j=i;
		while(buf[j]!=' '&&j<strlen(buf))
			j++;
		
		count=j;//记录空格位置 
		if(j!=strlen(buf)-1)//相当于到了末尾,就不进行减减了,减减是方便好进行单词内的字符转换 
			j--;
		while(i<j)
		{
			int a=buf[i];
			buf[i]=buf[j];
			buf[j]=a;
			i++;
			j--;
		}
		i=count;
	}
	puts(buf); 
	return 0;
 } 

9.去掉连续出现的K个0

题目分析:检测到0就再往后面检测k个,若都满足,就将空格后的字符串向前移动k个字符

//去掉连续出现的k个0
 #include<stdio.h>
 #include<string.h>
 int main(void)
 {
 	int k;
 	scanf("%d",&k);
 	char buf[100];
 	scanf("%s",buf);
 	int count=0;//记录是否有k个连续的0 
 	int count_num=strlen(buf);
 	for(int i=0;i<count_num;i++)
 	{
 		if(buf[i]=='0')
 		{
 			int j;
 			//这个for判断检测i后面的k个元素中有几个0 
 			for(j=i;j<i+k&&(j+k)<=count_num;j++)
 			{
 				if(buf[j]=='0')
				 count++;	
			 }
			 printf("%d\n",count);
			 if(count==k)//若上面for检测的有k个0,就要进行位移,否则就直接退出循环 
			 {
			 	while(j<count_num)
			 		{
			 			buf[j-k]=buf[j];
					 	j++;
					 }
			 	count_num-=k;
			 }
			 else
		 	{
		 		count=0; 
			 }
			 continue;
			 while(buf[i]=='0'&&i<count_num)//跳过后面的0 
				i++;
			i--;//上面的while跳到了正确的位置,由于for循环还有一个加加,所以这里就在减减一次 
			count=0; 
		}
	 }
	 for(int i=0;i<count_num;i++)
	 {
	 	printf("%c",buf[i]);
	 }
	 printf("\n");
 	return 0;
  } 

10.判断是否为回文数

题目分析:法一:利用快速排序双指针思想,两两比较即可

法二:开辟新的空间,翻转字符串,与原字符串进行比较,若相同就输出

//判断回文串
//法一:快速排序前后双指针,进行比较
//翻转后与原字符串相同
#include<stdio.h>
#include<string.h>
int main(void)
{
	char buf[100];
	gets(buf);
	//法一
//	for(int i=0,j=strlen(buf)-1;i<j;i++,j--)
//	{
//		if(buf[i]!=buf[j])
//		{
//			printf("bbbbu是回文串\n");
//			return 0;
//		}
//	 }
//	 printf("ssss是回文串\n");
	 //法二
	 char buf1[strlen(buf)];
	 for(int i=0,j=strlen(buf)-1;i<strlen(buf);i++,j--)
	 {
	 	buf1[i]=buf[j];
	  } 
	  puts(buf1);
	if(strcmp(buf1,buf))
		printf("bbbbu是回文串\n");
	else
		printf("ssss是回文串\n");
	return 0;
 } 

11.最短摘要

题目分析,一个一个单词的判断,若找到第一个元素,就可以对第二个元素进行标记,当前两个元素都已经标记,遇到第三个关键词就可以重新进行初始化。若在遇到第二个关键词之前,又遇到了第一个关键词,那么就要重新计数了。

//最短摘要
#include<stdio.h>
#include<string.h>
int main(void)
{
	char key1[]="one";
	char key2[]="two";
	char key3[]="ten";
	char danci_temp[100];
	int key1_log=0;//两个个关键词是否找到的标志位 
	int key2_log=0;
	int min_danci=100;//记录最小的摘要,因为essay数组都只有100个; 
	int danci_num=0;//记录实时的摘要数量 
	int count;//记录空格的下标 
	char essay[100];
	gets(essay);
	for(int i=0;i<strlen(essay);i++)
	{
		int j=i;
		while(essay[j]!=' '&&j<strlen(essay)-1)
			j++;
		count=j;//记录当前空格的位置
		if(key1_log==1)
			danci_num++;
		if(count==strlen(essay)-1)//当第三个关键词在最后的话,就会出错,因为count在空格的位置,那么去单词就是正确的,在末尾取单词就会少一个字符 
			count++;
		strncpy(danci_temp,essay+i,count-i);//截取单词 
		if(strcmp(key1,danci_temp)==0&&key1_log==0)
		{
			key1_log=1;
			danci_num=1;
		}
		//在没有找到第二个关键词之前,又遇到了第一个关键词那么就等重头再来 
		if(strcmp(key1,danci_temp)==0&&key1_log==1&&key2_log==0)
		{
			key1_log=1;
			danci_num=1;
		}
		if(strcmp(key2,danci_temp)==0&&key1_log==1&&key2_log==0)
			key2_log=2;
		if(strcmp(key3,danci_temp)==0&&key1_log==1&&key2_log==2)
		{
			 
			if(danci_num<min_danci)
			{
				min_danci=danci_num;
				key1_log=0;
				key2_log=0;
				danci_num=0;
			}
		}
		memset(danci_temp,0,sizeof(danci_temp));//初始化danci_temp数组为空,避免影响下一次单词的读取 
		i=count;
	}
	if(min_danci==100)
		printf("最小摘要为%d",0);
	else
		printf("最小摘要为%d",min_danci);
 } 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值