第四章 数据结构与算法- 串

来源:互联网 发布:网络配电箱250x300 编辑:程序博客网 时间:2024/05/19 02:43

      字符串数据是计算机非数值处理的主要对象之一。在早期字符串作为输入输出的变量出现,现已发展成为字符串类型,可以进行一系列的操作。

   字符串一般简称为串。在汇编和编译程序中,源程序是字符串数据。在事务处理程序中,顾客的姓名和地址以及货物的名称、产地等也是字符串。此外,如信息检索系统、文字编辑程序、自然语言翻译系统等都是以字符串为处理对象。

   然后,目前的计算机硬件结构主要是面向数值计算的需要,基本上没有提供处理字符串数据操作的指令,需要用软件来实现字符串类型。由于各种应用具有不同的特点,要有效的实现字符处理,必须根据具体情况使用合适的存储结构。

 

1、********************************************************************************************

****这里有两种基本算法:BF算法(Brute-Force,最基本的字符串匹配算法)、

****KMP算法。

BF算法:

#include <stdio.h>#include <stdlib.h>#include <string.h>/* run this program using the console pauser or add your own getch, system("pause") or input loop *//***************************************************************************这里A是主串,B是模式串.判断B是否为A的字串。 *****/int count=0;int main(int argc, char *argv[]) {char A[]="ababcdeec", B[]="abcdee";if(1 == StrBF(A, B, count)){printf("successed !\n");}else{printf("failed !");}printf("执行了%d次\n", count);return 0;}int StrBF(char A[], char B[]){int aLen = strlen(A);int bLen = strlen(B);int i,j=0;for(i=0; i<aLen; i++){if(A[i] == B[j]){j++;}else{i = i-j+1;j=0;}count++;if(j == bLen)return 1;}return -1;}

     

KMP算法:

      在KMP算法中,如果有部分字符已经匹配,即当前S[i] = T[j], 例S=cababc  T=ababd 可以说i=1,j=0,此时S[1]=T[0] ,那么现在i++,j++,继续匹配,直到S[i] !=T[j]的时候,那么此时i=5,j=4。这时候i不动,保持不变,并且让j=next[j],这里可能大家就迷惑了,next[j]哪里来的,为什么要让j=next[j] ?这就是KMP算法的难点,也是算法的核心。

       这里我具体描述一下,因为T中的abab是重复的,那么我们让 j = next[j] = 2 让 S[5]和 T[2]进行比较,毕竟我们知道S[3、4]=ab = T[2、3]=ab,同时T中的abab是重复的,所以只需 S[5]和 T[2]进行比较,就不用回溯到初试位置。这就是KMP的理念,寻找next[j]。

      

KMP算法分为两部分,首先计算next()函数,然后进行串匹配。

例如:T = ababd

j12345T[j]ababdnext[j]01121

现在KMP算法已经讲述的很清楚了,下面我们程序实现。


#include <stdio.h>#include <stdlib.h>#include <string.h>/* run this program using the console pauser or add your own getch, system("pause") or input loop *//***************************************************************************这里A是主串,B是模式串.判断B是否为A的字串。 ****char A[]="ababcdeec", B[]="abab";****只有形参为指针的时候才能改变实参的值 */int *StrKmpNext(char B[]);int main(int argc, char *argv[]) {char A[]="ababcdeec", B[]="abab";int *p;int len;len = strlen(B); p = StrKmpNext(B);p++;while(-1 != *p){printf("%d\t", *p++);}printf("执行了%d次\n", len);return 0;}//求取next数组 int *StrKmpNext(char B[]){int bLen = strlen(B);int i=0,j=0;int *next = malloc(sizeof(int)*bLen+8);//这里next[1] - next[bLen] - next[bLen+1]for(i=0; i<=bLen; i++){next[i] = 0;}next[1] = 0;i = 1;while(i<bLen){if(B[i] == B[j] || j==0){i++;j++;next[i] = j;}else{j = next[j];}} next[i+1] = -1;return next;}
根据已经拿到的next值,使用KMP算法判定B是否为A的字串。

#include <stdio.h>#include <stdlib.h>#include <string.h>/* run this program using the console pauser or add your own getch, system("pause") or input loop *//***************************************************************************这里A是主串,B是模式串.判断B是否为A的字串。 ****char A[]="ababcdeec", B[]="abab";****只有形参为指针的时候才能改变实参的值 */int *StrKmpNext(char B[]);int main(int argc, char *argv[]) {char A[]="adababeec", B[]="abab";int *p;int len;int i,j=0;len = strlen(B); p = StrKmpNext(B);p++;//****kmp算法的实现过程 for(i=0; i<strlen(A); i++){if(A[i] == B[j]){j++;if(j == len){printf("B是A的字串\n");return;}}else{j = p[j+1];}}printf("B不是A的字串\n");return 0;}//求取next数组 int *StrKmpNext(char B[]){int bLen = strlen(B);int i=0,j=0;int *next = malloc(sizeof(int)*bLen+8);//这里next[1] - next[bLen] - next[bLen+1]for(i=0; i<=bLen; i++){next[i] = 0;}next[1] = 0;i = 1;while(i<bLen){if(B[i] == B[j] || j==0){i++;j++;next[i] = j;}else{j = next[j];}} next[i+1] = -1;return next;}
KMP算法在判断是否为某一串的字串时,若匹配串重复度特别高,则效率会特别明显。

2、/*********************************************
****给定字符串A和B,输出A和B中的最大公共子串。
****比如A="aocdfe" B="pmcdfa" 则输出"cdf"

#include <stdio.h>#include <stdlib.h>#include <string.h>/*************************************************给定字符串A和B,输出A和B中的最大公共子串。****比如A="aocdfe" B="pmcdfa" 则输出"cdf" /* run this program using the console pauser or add your own getch, system("pause") or input loop */char *commanstring(char shortstring[],char longstring[]);int main(int argc, char *argv[]) {char *str1 = "aocdfe";char *str2 = "aocfe";char *comman = NULL;if(strlen(str1)>strlen(str2))comman= commanstring(str2,str1);elsecomman = commanstring(str1,str2);printf("the longest comman string is:%s\n",comman);return 0;}char *commanstring(char shortstring[],char longstring[]){int i,j;char *substring = malloc(256);int lenShort = strlen(shortstring);if(strstr(longstring,shortstring)!=NULL)return shortstring;for(i=lenShort-1;i>0;i--){for(j=0;j<=lenShort-i;j++){memcpy(substring,&shortstring[j],i);substring[i]='\0';if(strstr(longstring,substring)!=NULL)return substring;}}return NULL;}

3、/*********************************************
***如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,

***问如何在迅速匹配兄弟字符串(如,bad和adb就是兄弟字符串)。

 

#include <stdio.h>#include <stdlib.h>/* run this program using the console pauser or add your own getch, system("pause") or input loop *如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,问如何在迅速匹配兄弟字符串(如,bad和adb就是兄弟字符串)。思路:判断各自素数乘积是否相等。更多方法请参见:http://blog.csdn.net/v_JULY_v/article/details/6347454。*date:2013/11/2 *@author_hanzhen*/int main(int argc, char *argv[]) {char A[]={"bad"},B[]={"adb"};if(array(A,B) == 1)printf("A and B are the brothers!");elseprintf("NO,error!");return 0;}int array(char A[],char B[]){int i=0;char *a, *b;int Aresult[26]={0},Bresult[26]={0};a = A;b = B;if(strlen(A)!=strlen(B))  return -1;i=0;while(i<strlen(A)){ i++;Aresult[*a-'a']++;a++;Bresult[*b-'a']++;b++;//printf("%d\n", i);}for(i=0;i<26;i++){if(Aresult[i]!=Bresult[i]){return -1;}}if(i>=26)return 1;}


 

 

原创粉丝点击