算法---字符串匹配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011467044/article/details/55008649

编辑文本时,我们经常需要在文本中找到某串模式字符在整个文本中出现的位置,这个模式字符串即为用户查找输入的关键字,解决这个问题的算法为字符串匹配算法。 
这里写图片描述 
当我们遇到这个问题,如何查找在文本中出现的模式呢? 
一:朴素字符串匹配 
我们假设存在两个游标i,j分别指向文本串与模式串的位置,那么有 
1:当匹配到T[i]==P[j],则i++,j++; 
2:当在匹配到某一位置时出现T[i]!=P[j]时,即匹配失败,此时i回溯到本次开始匹配的位置,j=0 
咱们从代码与匹配图解理解朴素算法思路:

int native_string_matcher(char* T,char* P)
{
//获取原始串和模式串字符长度
    int n=strlen(T);
    int m=strlen(P);
    int s=0,i=0;
    //原串开始从0至n-m偏移,以匹配模式串
    for(s=0;s<=n-m;s++)
    {
//模式串从0-m开始分别匹配模式串中字符是否与原串相等
        for(i=0;i<m;i++)
        {
            if(P[i]!=T[s+i]) //如果在匹配过程中有字符不相等,则跳出该循环,偏移S向下移位,继续重新匹配
            {
                    break;
            }
            if(i==m-1)//当i=m-1,且P最后字符与T最后字符相等,则表示字符串匹配成功,此时返回原串中与模式串相匹配的起始位置。
                    printf("has match");
                    return s;
        }
    }
}

OK,现在我们举个栗子, 
假设有一个文本字符串和模式字符串如下图 
这里写图片描述 
(a) 字符串开始匹配,此时T[0]=P[0],i++为1,此时s+i=1,T[1]!=P[1],匹配失败,s自加1,变为1,开始图(b)的匹配过程; 
(b) 此时T[s=1]=c!=P[0],匹配失败,s自加1,变为图c的匹配过程 
(c) 此刻T[s=2]=P[0],i自加1,T[s+i=3]=P[i=1],字符相等,继续下一匹配,i自加1为2,T[s+i=4]=P[i=2],且此刻i=length(P),匹配结束。此刻,s继续自加,进行余下字符串的匹配。 
朴素字符串匹配过程较简单,但是最坏情况下时间复杂度为O((n-m+1)*m),字符串的匹配时间开销较大,并不能很好的解决字符串的匹配。 
补充: 
在朴素字符串匹配中存在一种特殊情况,即模式串P中的所有字符都不相同,其匹配时间可以达到O(n),具体的实现代码如下:

int native_string_matcher(char* T,char* P)
{
//获取原始串和模式串字符长度

    int n=strlen(T);
int m=strlen(P);
    int j=0,i;
    for(i=0,j=0;i<n;i++)
    {
            if(T[i]==P[j]&&j<m) ++j;

            else{
                if(j!=0)
                {
                    j=0;
                    --i;
                }
            }
            printf("%d\n",i);
            if(j==m)
                return i-m+1;
    }
    return -1;//若为-1,代表原始串中不包含模式串
}

这个实现过程很好理解,下面图示匹配过程: 
这里写图片描述 
整个匹配流程如下: 
(1) 文本串i=0,模式串j=0,此时T[i]!=P[j],匹配失败,i自加1; 
(2) 开始匹配,T[1-4]=P[0-3],但T[5]!=P[4],匹配失败,由于P中所有字符互不相同,所以i不必回溯到T[i=2],只需开始匹配T[i-1=4]与P[0]并开始新一轮的匹配过程。

至此,朴素字符串匹配算法结束,整个过程很好理解。

posted @ 2019-01-17 16:07  sungogo  阅读(238)  评论(0编辑  收藏  举报