字符串的算法总结

1、按单词反转字符串

问题:

单词用空格分开的字符串,如 Here is blog.csdn.net/chenjiayi 经过反转后变为:blog.csdn.net/chenjiayi is Here

方法:

1)遍历字符串,将第一个字符和最后一个字符交换,第二个字符和倒数第二个字符交换,以此类推。

2)遍历一遍字符串,按照单词反转,对每一个单词再反转一次

代码如下:  

char * reverseWord(const char *str){  
  int len = strlen(str);  
  char * restr = new char[len+1];  
    
  strcpy(restr,str);  
  char tmp; 
  //首尾交换,i是首的索引 j是尾的索引   
  for(int i=0,j=len-1;i<j;++i,--j){  
      tmp = restr[i];  
      restr[i] = restr[j];  
      restr[j] = tmp;  
  }  
    
  //再把每个单词反转   
  int i,j,k = 0;  
  
  while(k<len){  
  		while(len > k && restr[k] == ' ')++k;//跳过空格,找到下一个单词开始   
      i = j = k;  
      while(restr[j]!=' ' && restr[j]!='\0')  
          ++j;//查找空格的索引   
        
      k = j;//记录空格索引
    
      //反转单词   
      char tmp;
      for(--j;i<j;++i,--j){  
          tmp = restr[i];  
          restr[i] = restr[j];  
          restr[j] = tmp;  
      }  
  }  
    
  return restr;  
}  


2、字符串反转

题意:给定一个字符串,一个这个字符串的子串,将这个字符串反转,但保留子串的顺序不变。

例如:输入 每一个串 “this is wufl's Chinese site: http://blog.csdn.net/wufenglong”

子串:“wufl”

输出: gnolgnefuw/tne.ndsc/golb//:ptth:eits esenihC s'wufl si siht

说明:

扫描一遍字符串,扫描中如果发现子串,就将子串倒过来压入数组末尾,否则就正向压入字符串的字符到数组末尾。最后翻转数组字符。

代码如下: 

//字符串 str ,子串token
char* reverseStr(const char * str, const char * token){  
  assert(str && token);  
    
  char * array = new char[strlen(s1)+1];  //数组
  int   arrayIndex = 0;
  const char * ptoken = token, *head = str, *rear =str;  
    
  while(*head){  
      while(*head && *ptoken == *head){  
          ptoken++;  
          head++;  
      }  
        
      if(*ptoken=='\0'){  //是一个子串
          const char *p;  
            
          for(p=head-1;p>=rear;p--){  //反向压入字符子串
              array[arrayIndex] = *p;  
              ++arrayIndex;
          }  
          rear = head;//跳过子串   
      }else{  //不是一个子串
      	  array[arrayIndex] = *rear;  //正向压入字符串的字符
          ++arrayIndex ;   
          head = ++rear;  //跳过一个字节
      }  
      ptoken = token;  //重新记录子串位置
  }  
    
  array[arrayIndex] = 0;
  int i,j = 0;  
  char tmp;
  //翻转数组
  for(i = arrayIndex-1;j < i;--i,++j)  
  {
  	tmp =  array[j];
  	array[j] = array[i];
  	array[i] = tmp;
  }
  return array;
}  


3、获取两个字符串最大子串

3种实现方式:

(1)c风格 不使用字符串相关的api

#include <iostream> 
#include <string> 
using namespace std; 

char * longestCommonSubstring(const char *str1, const char *str2) 
{
	if(!str1 || !str2)return NULL;
	int strLen1 = strlen(str1);
	int strLen2 = strlen(str2);
	int minLen = (strLen1 < strLen2) ? strLen1:strLen2;
	if(!minLen)return NULL;
	int count;
	for (int i = minLen;i>0;i--)//最大字串长度尝试是从大到小
	{
		for (int j = 0;j < strLen2;j++)
		{
			const char *tmpStr1Start = str1;
			const char *tmpStr2Start = str2 + j;//第二个字符串中的子串开始位置
			for (;(tmpStr1Start+i-1)[0];tmpStr1Start++)//第一个字符串中的子串开始位置
			{
				const char *tmpStr1 = tmpStr1Start;
				const char *tmpStr2 = tmpStr2Start;
				count = 0;
				while (*tmpStr1++ == *tmpStr2++ && ++count <= i);//子串长度
				if (count >= i)//最大子串
				{
					char *tmpStr = (char *)malloc(count + 1);
					memcpy(tmpStr,tmpStr2Start,count);
					(tmpStr + count)[0] = 0;
					return tmpStr;
				}
			}
		}
	} 
	return NULL;
}




(2)c风格 ,使用了strncmp

char * longestCommonSubstring2(const char *str1, const char *str2) 
{
	int strLen1 = strlen(str1);
	int strLen2 = strlen(str2);
	int minLen = (strLen1 < strLen2) ? strLen1:strLen2;
	
	for (int i = minLen;i>0;i--)
	{
		for (int j = 0;j < strLen2;j++)
		{
			const char *tmpStr1Start = str1;
			const char *tmpStr2Start = str2 + j;
			for (;(tmpStr1Start + i)[0] != 0;tmpStr1Start++)
			{
				if(0 == strncmp(tmpStr1Start,tmpStr2Start,i))
				{
					char *tmpStr = (char *)malloc(i + 1);
					memcpy(tmpStr,tmpStr2Start,i);
					(tmpStr + i)[0] = 0;
					return tmpStr;
				}
			}
		}
	} 
	return "";
}

(3)c++风格

string longestCommonSubstring3(string const& s1, string const& s2) 
{ 
	int n = min(s1.length(), s2.length()); 
	int len1 = s1.length(); 
	string ss; 
	for (int i = n; i > 0; --i) 
	{ 
		for (int j = 0; j <= len1-i; ++j) 
		{ 
			ss = s1.substr(j, i); 
			if (s2.find(ss, 0) != string::npos) 
			{ 
				return ss; 
			} 
		} 
	} 
	return string(); 
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值