第二章---串

#include <stdio.h> 
#include <typeinfo.h>
#define MAXN 100

typedef enum{
	fail,
	success
} status;



//1.求出串s的长度,strlen(s)的值是一个非负整数。若s是一个空串,则strlen(s)=0 
int strlen(char s[])
{
	int i;
	i=0;
	
	//while(s[i++]!='\0');//注意区别 i的长度包括了 '/0' 
	
	for(i=0;s[i]!='\0';i++); //i的长度不包括'/0' 

	return i;
}

//2.strcat(s1,s2) 把串s2加到s1的末尾
status strcat(char s1[],char s2[])
{
	int i,j,k;
	
	if((i=strlen(s1))+(j=strlen(s2))>=MAXN)
	      return fail;
	      
	for(k=0;k<=j;k++)
	      s1[i+k]=s2[k];
	      
	return success;    
}
 

//3.strsub(s1,i,j,s2) 把串s1中位置i开始取长度为j的子串构成串2l
status strsub(char s1[],int i,int j,char s2[])
{
	int m,k;
	
	if(i<0||i>=(m=strlen(s1)))
		 return(fail);
    if(j<0||i+j>m)
         return fail;

	for(k=0;k<j;k++)
		 s2[k]=s1[k+i];
		 
	s2[k]='\0';
	return success;  
}

//4. strins(s1,i,s2) 把串s2插在串s1的位置i上
status strins(char s1[],int i,char s2[])
{
	int m,n,k;
	if(i<0|| i>(m=strlen(s1)) || m+(n=strlen(s2))>MAXN)
	     return fail;
	for(k=m;k>=i;k--)
	  s1[k+n]=s1[k];          //后移
	
	for(k=0;k<n;k++)
		s1[i+k]=s2[k];
	   
	return success;       
}

//5. strdel(s,i,j) 把从s中位置i开始,删除j个字符。如果字符个数不足j,则全删除
status strdel(char s1[],int i,int j)
{
	int n,m;
	if(i<0||i>(n=strlen(s1)))
	   return fail;
	if(i+j>=n)
	   s1[i]='\0';
	else   
	    for(m=0;m<=n-i-j;m++)
	        s1[i+m]=s1[i+j+m];
	return success;        
}

//6. strequ(s1,s2)   判断s1和s2是否相同
bool strequ(char s1[],char s2[])
{
	int i=0;
	while(s1[i]==s2[i] && s1[i]!='\0'&&s2[i]!='\0')
	      i++;
	if(s1[i]=='\0' && s2[i]=='\0')
	    return true;
	else
	    return false;
}

//7. strstr(s1,s2)   s2首字符在s1中的位置 


//8. 简单匹配算法
int simple_match(char t[],char p[],int n,int m)
{
	int i,j,k;
	for(i=0;i<=n-m;i++){
		for(j=0,k=i;j<m&&t[k]==p[j];j++,k++)
		    ;
		if(j==m) return i;	
	}
	return -1;
}

//kmp 失败数组 
void faillink(char p[],int flink[],int m)
{
	int j,k;
	flink[0]=-1;
	j=1;
	while(j<m){
		k=flink[j-1];
		while(k!=-1&&p[k]!=p[j-1])
		    k=flink[k];
		
		flink[j]=k+1;
		j++;
	}
}

//kmp 算法
int flink[100];
int kmp_match(char t[],char p[],int n,int m)
{
	int i,j;
	i=j=0;
	while(i<n){
		while(j!=-1&&p[j]!=t[j])
		     j=flink[j];
		if(j==m-1)   return (i-m+1);
		
		i++;
		j++;
	}
	return -1;
}


//bm 算法  d数组
void df(char p[],int d[],int m)
{
	int i;
	for(i=0;i<26;i++)
	   d[i]=m;
	for(i=0;i<m-1;i++)
	   d[p[i]-'a']=m-i-1;
}

int d[26];
//bm
int bm_match(char t[],char p[],int n,int m) 
{
	int i,j,k;
	i=m-1;
	do{
		j=m-1;
		k=i;
		while(j>=0&&p[j]==t[k]){
			j--;
			k--;
		}
		if(j<0) return(i-m+1);
		i=i+d[t[i]-'a'];
	}while(i<n);
	
	return -1;
}


//2.1 假设s和t分别具有m和n个字符,寻找s和t中最大公共子串 

//2.1.1 暴力破解
int constring_1(char s[],char t[],int m,int n)
{
	int i,j,k,max;
	int index,length;
	i=index=length=0;
	
	while(i<n){
		j=0;
		while(j<m){
			if(s[i]==t[j]){
				max=1;
				for(k=1;s[i+k]==t[j+k];k++)
				     max++;
				     
				if(max>length){
					index=i;
					length=max;
				}
			}
			
			j++;
			
		} //end j<m
		
		i++;
	}//end i<n
	
	printf("最大公共子串:");
	for(i=0;i<length;i++)
	      printf("%c",s[index+i]);
}

//2 动态规划  待续 
void  constring(char s[],char t[],int m,int n)
{
  
}

//2.2假设所使用的串采用链接存储结构,每个节点可存放m(m=4) 个字符。编写strins(s1,i,s2)
//的c函数。为了减少移动字符的次数,节点中允许使用无效的特殊字符,但一个结点至少含有一个有效字符。 

/*
   算法步骤:
   1.通过i/4算出所在节点
   2.通过k=i%4 算出i在该节点中的位置
   3.开设一新节点,把该节点k后的字符赋值给新节点
   4.把该节点中赋值过的字符及新节点中未赋值的都置为无效字符‘*’ 
   5.使新节点指向该节点的后继,该节点指向s2首节点,并把s2的末节点中的‘\0’置成‘*’,末节点指向新节点 
    
	若 S1="ABCDEFGHI"  S2=“JML”i=6 则调用后为 ABCD EF** JML*GH**I
*/
#include <stdlib.h>

typedef struct node{
	char data[4];
	struct node *link;
} Node;

void strins(Node *s1,int i,Node *s2) 
{
	int j,k,l,m;
	Node *p,*q,*r;
	
	j=i/4;						//所在节点 
	k=i%4;						//所在节点位置
	p=s1;
	
	r=s2;
	while(r->link!=NULL)      //r指向最后一个节点 
	     r=r->link;      
	for(m=0;r->data[m]!='\0';m++);
	     r->data[m]='*';
	
	while(m<4)
	     r->data[++m]='*'; 	
	
	
	for(l=1;l!=j;l++) 
	     p=p->link;              //k=0的情况,p指向s2将插入的节点 
	
	if(k==0){
		q=p->link;
		p->link=s2;
		r->link=q;
		return; 
	}
	
	if(k!=0){					//k!=0 原节点分为两个节点,首尾分别填充* 
	    p=p->link;
		q=(Node*)malloc(sizeof(Node));
		
	   for(m=k;m<4&&p->data[m]!='\0';m++)
		{
			q->data[m-k]=p->data[m];
			p->data[m]='*'; 		//'*' is invalid char 
		}
		
	   if(p->data[m]=='\0'){
	   		q->data[m-k]='\0';      //p指向的节点不足4个 
	   		p->data[m]='*';
	   }         
	   else{
	    	for(l=k;l<4;l++)
		       q->data[l]='*';
		}
	
	}	
     
	     
	q->link=p->link;
	p->link=s2;
	r->link=q; 
	
}

//2.3 按照2.2题的要求,编一个实现strdel(Node *s,int i,int j)的c函数   从i开始删除j位字符 
/*
	1. 计算出S中节点的个数L
	2.通过 i/4  计算出其在S中的节点位置
	3.通过i%4计算出其在该节点中的位置
	4.若(i+j-1)/4>L  则置该位置为‘/0’
	 否则,将i位所在结点中的所在位及其后均置为‘*’
	 并将(i+j-1)/4所在结点中的所在位及其前均置为‘*';
	5.最后使i位所在结点指向(i+j-1)/4所在结点 
*/
void strdel(Node *s,int i,int j)
{
	int k,l,m,h;
	Node *q,*p;
	
	k=i/4;
	h=i%4;
	
	l=0;		//节点个数 
	q=p=s;
	
	if(i<0||j<0){
		printf("输入不符合格式");
		exit(1);
	}
	
	while(p->link!=NULL){
		p=p->link;
		l++;
	}

	p=s;					//p重置 
	for(m=0;m!=k;m++) 
			p=p->link;	    //p定位到i所在结点
			
	if((i+j-1)/4>l){	    //i后全删除 
		p->data[h]='\0';
		p->link=NULL;
	}else{
		for(m=0;m!=(i+j-1)/4;m++)
		        q=q->link;               //q定位到(i+j-1)所在结点 
		for(m=h;m<4;m++)
				p->data[m]='*';		   //i后置为‘*’ 
		for(m=(i+j-1)%4;m>=0;m--)
			    q->data[m]='*';         //'i+j-1'前置为‘*’
				 
	  if((i+j-1)/4==k) 
	          return;        //在同一个节点内 
	          
	   p->link=q;
	}
	     

	
}

int main()
{
	Node s1={{'A','B','C','D'},NULL};
	Node r={{'E','F','G'},NULL};

	s1.link=&r;
	Node s2={{'J','M','L'},NULL};
	
	Node*a=&s1;
	Node*b=&s2;
	
	
//	strins(a,5,b);
	
	strdel(a,3,6);

	int i=0;
	while(a){
		for(int i=0;i<4;i++)
		      printf("%c",a->data[i]);

		a=a->link;
	}

}

猜你喜欢

转载自blog.csdn.net/qq_16829085/article/details/82962458