KMP算法


  求一个字符串T的子串S的位置一般算法是
int len=T.len-S.len,j,i;
for(i=0;i<len;i++)
{   
    for(j=0;j<S.len;j++)
        if(T[i+j]!=S[j]) break;
    if(j==S.len) break;
}

这种算法写起来很简单,复杂度最大为O(T.len*S.len)
例如T[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAaaaaaaaaaa"; 
而S[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAA" ;
 这样的数据会使内嵌的for()每次都循环S.len() 次,如果这两个串又是特别长的话,程序效率将会特别低下;


KMP算法就出来了的。
讲这个算法之前,先说一下next[ ]数组
这个数组的每一个元素,都对应着S串中的每一个字符
    S = {a,c,a,d,c,a,d}
next.={0,1,1,2,1,1,2} 
 

    . S={a,b,c,c,a,b,c}
  next={0,1,1,1,1,2,3} 

next[i]中的值,即为S[i]之前的序列能和S从开头算起的最大重合的个数+1; 
比如 :
             0 1 2 3 4 5 6
       S={a,b,c,c,a,b,c}
  next={0,1,1,1,1,2,3}  
其中next[6]=3,是因为S[6]前面有S[4]=a;
                                                   S[5]=b;
而S[0]=a;
    S[1]=b;
重合,所以next[6]记为3;

为什么不记为4?
因为S[0]=a;
       S[1]=b;
       S[2]=c;
而S[3]=c;
    S[4]=a;
    S[5]=b;
显然不符合.....


总而言之,next【i】的值就是  S[i]中,若 i 左移k位,得到得S[i-k]~S[i]这个子串与S[0]~S[k]相同,那么next[i]的值即为所能取到的最大的k再加上1;
注:next[]的值,以及元素的个数都只与S串有关,它是描述S串属性的量(S串是子串) 

next[]数组的作用是:当确定一个首地址i,接着向后寻找时,找了m次都成功S与T都成功匹配上了(字符相同),但是,找到m+1位,发现S与T不一样了,之前那种一般算法就是i向下挪一位,接着j=0重新开始查找,但是我如果有next[]数组我就可以很轻易的得知m+1位的前next[m+1]-1位,一定是和T匹配上的,然后j直接向后挪动next[m+1]位比较,直到next[]=1;(事实上根本用不了几次)然后i直接就可以向下 挪一位;


int i=0,j=-1;
next[0]=-1;
while(i<s.length())
{
    if(j==-1||s[i]==s[j])
    {
        i++;
        j++;
        next[i]=j;
    }
    else j=next[j];
}
//求next的代码
int find(const string& t,const string& s)
{
    int i=0,j=0;//可以通过改变i的值,查找第i位后的s串
    while(i<(int)t.length()&&j<(int)s.length())//string.length()返回值是无符号整型
    {
        if(j==-1||t[i]==s[j])
        {
            i++;
            j++;
        }
        else j=next[j];
    }
    if(j==t.length()) return i-t.length();
    else return -1;
}



next[]数组的改进求法
int i=0,j=-1;
next[0]=-1;
while(i<s.length())
{
    if(j==-1||s[i]==s[j])
    {
        i++;
        j++;
        if(s[i]!=s[j])
        next[i]=j;
        else next[i]=next[j];
    }
    else j=next[j];
}



2016年追加:
我不知道当时为什么那么奇葩的把next[]数组构造成那样,不过既然思想没有错,那我就保留当时的我的看法,不改前面了,今天回过头来看了一下,发现对next[]数组的作用描述的不够清晰,我再重新描述一下吧
字符串为T,子串为S,当比较到T[i]与S[j]时,发现T[i]与S[j]不相等,首先这里要明确一个问题,此时T[i-j]==S[0],T[i-j+1]==S[1],T[i-j+2]==S[2]....
T[i-1]==S[j-1];意思就是,S[j]之前的与T[i]之前的完全相等。所以就牵扯到一个重复的问题,比如S=="abcabdc"如果现在j=5时,发现不等,那么T[i-2]=='a',T[i-1]=='b',我只需再比较T[i]==S[2]。说白了,next[]串记录的就是,如果比较到这一位,发现不等,那么,T[i]要重新和S[i]的第几位比较。当然如果S[0]的位置出现不相等了,那么i就必须向下挪一位了。,所以不妨把这种情况标记为-1
刚刚说 S=="abcabdc"很容易得到next[]="-1,0,0,0,1,2,0",代码上面已经给出了,虽然跟我现在说的有点不一样,稍微做些改变就可以了。

2018/04/08追加:

距离写下这篇博客(2014年)已经过去4年了,无意中又翻到了这篇博客,2014年写的东西太乱,况且只是生搬教材的东西,不做评价。只评价一下2016年写的追加内容。

我在2016年追加写到“ S=="abcabdc"很容易得到next[]="-1,0,0,0,1,2,0" ”。这个说法是有点问题的,首先再明确一下next数组是什么。next数组中的第i个值代表:当前字符与s[i]对比失败,要和s[next[i]] 继续对比,next存的是比较失败后的合格前缀,next[x] = -1代表没有合适前缀,s[i]需要后移。再看next数组,明显是有问题的,比如next[3]:s[3]就等于s[0],如果比较失败后,没必要再和s[0]比,多比较了一次。比如next[4]:s[4]比较失败,应该直接和s[0]比较,也多比较了一次。next数组十分关键,决定了匹配效率。例子中冗余比较只有一个维度不多,但是在串比较长的情况下,可能出现多度冗余(next[i]无效比较多次,才进行有效的比较)影响效率。

正确的next[] = "-1,0,0,-1,0,2,0"

贴一下next[]的生成代码:

vector<int> getKmpNext(string &s){
    vector<int> next(s.sie(),-1);
    for(int i=1,j=0;i<s.size();i++){
        if(s[i] == s[j]){
            next[i] = next[j];
                j++;
        }else{
            next[i] = j;
            while(j != -1 && s[i] != s[j])
                j = next[j];
            j++;
        }
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数字乡村和智慧农业的数字化转型是当前农业发展的新趋势,旨在通过应用数字技术,实现农业全流程的再造和全生命周期的管理服务。国政府高度重视这一领域的发展,提出“数字国”和“乡村振兴”战略,以提升国家治理能力,推动城乡融合发展。 数字乡村的建设面临乡村治理、基础设施、产业链条和公共服务等方面的问题,需要分阶段实施《数字乡村发展战略纲要》来解决。农业数字化转型的需求包括满足市民对优质农产品的需求、解决产销对接问题、形成优质优价机制、提高农业劳动力素质、打破信息孤岛、提高农业政策服务的精准度和有效性,以及解决农业融资难的问题。 数字乡村建设的关键在于构建“1+3+4+1”工程,即以新技术、新要素、新商业、新农民、新文化、新农村为核心,推进数据融合,强化农业大数据的汇集功能。数字农业大数据解决方案以农业数字底图和数据资源为基础,通过可视化监管,实现区域农业的全面数字化管理。 数字农业大数据架构基于大数据、区块链、GIS和物联网技术,构建农业大数据心、农业物联网平台和农村综合服务指挥决策平台三大基础平台。农业大数据心汇聚各类涉农信息资源和业务数据,支持大数据应用。信息采集系统覆盖市、县、乡、村多级,形成高效的农业大数据信息采集体系。 农业物联网平台包括环境监测系统、视频监控系统、预警预报系统和智能控制系统,通过收集和监测数据,实现对农业环境和生产过程的智能化管理。综合服务指挥决策平台利用数据分析和GIS技术,为农业决策提供支持。 数字乡村建设包括三大服务平台:治理服务平台、民生服务平台和产业服务平台。治理服务平台通过大数据和AI技术,实现乡村治理的数字化;民生服务平台利用互联网技术,提供各类民生服务;产业服务平台融合政企关系,支持农业产业发展。 数字乡村的应用场景广泛,包括农业生产过程、农产品流通、农业管理和农村社会服务。农业生产管理系统利用AIoT技术,实现农业生产的标准化和智能化。农产品智慧流通管理系统和溯源管理系统提高流通效率和产品追溯能力。智慧农业管理通过互联网+农业,提升农业管理的科学性和效率。农村社会服务则通过数字化手段,提高农村地区的公共服务水平。 总体而言,数字乡村和智慧农业的建设,不仅能够提升农业生产效率和管理水平,还能够促进农村地区的社会经济发展,实现城乡融合发展,是推动国农业现代化的重要途径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值