数据结构复习练手之nyoj5

本题主要涉及到kmp算法中的匹配问题,查阅严版数据结构书中p80可知该算法分为两步:
1.对需要查找的字段Strb生成相关next数组,next数组表示当前字符i不匹配时,不回溯,而从Strb的next[i]位置开始匹配。next数组是反映须查找字段strb本身的特性,与待查找文本stra无关。
附上next数组求法:(strb为查找目标字段,stra为需要查找strb字段的文本)

1.next数组前1,2位一定是0,1;
2.第三位开始,设当前位为j,令k=next[j-1]
3.比较strb[j-1]与strb[k]是否相等。如果相等,那么next[j]=K+1,否则,k=next[k]。
4.若k=0,则next[j]=1,若k不等于0则跳转第3步直到k=0或strb[j-1]与strb[k]相等为止。

可能有些同学查阅相关文章发现有的next数组前两位是从-1,0开始的,这是由于数组下标定义的不同,如上方法定义数组下标从1开始,而从-1,0开头的next数组下标是从0开始的。
附上-1,0开头的next数组求法:

void get_next(char str[]){
    int i=0,j=-1;
    next[0]=-1;
    while(istr)){
        if(j==-1||str[i]==str[j]){
            i++;
            j++;
            next[i]=j;
        }else{
            j=next[j]; 
        }
    }
}

2.生成了next数组之后,便是在需要查找的字段stra中匹配目标字段strb了。

int getans(char stra[],char strb[]){//stra为查找文本,strb为目标单词 
    int i=0; 
    int j=0;
    int ans=0;//段落中目标字符串的个数
    while(i<(int)strlen(stra)){
        if(j==-1||stra[i]==strb[j]){//如果文本stra已经匹配完就跳出
            i++;
            j++;//如果相等的话继续匹配下一个。
        }else{
            j=next[j];//跳到指定位置继续匹配。
        }
        if(j>=(int)strlen(strb)){//当匹配成功时
             ans++;
             i=i-strlen(strb)+1;//stra的位置回溯到下一个字符
             j=0;//strb从头开始匹配
         }
    }
    return ans;  
}

通过这两步就可以用kmp的方式解决这个问题。以下是ac代码


#include
#include
#include
using namespace std;
char stra[1002];
char strb[1002];
int next[22];
int n;
void get_next(char str[]){
    int i=0,j=-1;//int i=1,j=0;
    next[0]=-1;
    while(i<strlen(str)){
        if(j==-1||str[i]==str[j]){
            i++;
            j++;
            next[i]=j;
        }else{
            j=next[j]; 
        }
    }
}
int getans(char stra[],char strb[]){//stra为查找文本,strb为目标单词 
    int i=0; 
    int j=0;
    int ans=0;
    while(i<(int)strlen(stra)){
        if(j==-1||stra[i]==strb[j]){
            i++;
            j++;
        }else{
            j=next[j];
        }
        if(j>=(int)strlen(strb)){
             ans++;
             i=i-strlen(strb)+1;
             j=0;
         }
    }
    return ans;  
}
int main(){
    scanf("%d",&n);
    for(int i=0;iscanf("%s%s",strb,stra);
        get_next(strb);
        int ans=getans(stra,strb);
        printf("%d\n",ans);
    }
    return 0;
}        

你可能感兴趣的:(数据结构)