zoukankan      html  css  js  c++  java
  • KMP 专题知识

         http://www.cnblogs.com/zhangtianq/p/5839909.html 

         这个博客主要是理解KMP(字符串普通匹配)

    普通next:

     1 ///这里还是不要用next命名数组啦
     2 
     3 void findnext()
     4 {
     5     memset(nextt,0,sizeof(nextt));
     6     int j=0,k=-1;
     7     nextt[0]=-1;
     8     int len=strlen(b);
     9     while(j<len)
    10     //while(j<len-1)
    11     {
    12         if(k==-1||b[k]==b[j])
    13         {
    14             k++;j++
    15             nextt[j]=k;
    16         }
    17         else
    18             k=next[k];
    19     }
    20 }
    basic next

    普通kmp:

     1 int kmp()
     2 {
     3     int i=0,j=0;
     4     int sa=strlen(a),sb=strlen(b);
     5     while(i<sa&&j<sb)
     6     {
     7         if(j==-1||a[i]==b[j])
     8         {
     9             i++;
    10             j++;
    11         }
    12         else
    13         {
    14             j=nextt[j];
    15         }
    16     }
    17     if(j==sb)
    18         return i-j+1;
    19     else
    20         return -1;
    21 }
    kmp 这里求第一个相同串的位置

    下面针对next数组的其他应用:

    1、求模式串在目标串中的出现次数;

         修改了一下kmp即可:

     1 ///可重叠
     2 
     3 int kmp()
     4 {
     5     int i=0,j=0,ans=0;
     6     int sa=n,sb=m;
     7     while(i<sa)
     8     {
     9         if(j==-1||a[i]==b[j])
    10         {
    11             i++;
    12             j++;
    13         }
    14         else
    15         {
    16             j=nextt[j];
    17         }
    18         if(j==sb)
    19         {
    20             j=nextt[j];ans++;
    21         }
    22     }
    23     return ans;
    24 }
    kmp 求相同串的个数(可重叠)
     1 int kmp()
     2 {
     3     int i=0,j=0,ans=0;
     4     int sa=strlen(a),sb=strlen(b);
     5     while(i<sa)
     6     {
     7         if(j==-1||a[i]==b[j])
     8         {
     9             i++;j++;
    10         }
    11         else
    12             j=nextt[j];
    13         if(j==sb)
    14         {
    15             j=0;ans++;
    16         }
    17     }
    18     return ans;
    19 }
    kmp 不可重叠

    2、求一个字符串中最长子串(整一个字符串=n*子串)。

    比如字符串:abcabcabc 。目测其最长子串为:abc,长度为3。

    next数组中,每一个字符的值:

    下标 0 1 2 3 4 5 6 7 8 len
    字母 a b c a b c a b c
    next -1 0 0 0 1 2 3 4 5 6

    next[len] :是在字符串最后一个字符后面的假设的一个位置。也就是说要是b[len]匹配失败,但在这之前,已经有6个字符时匹配成功的了,因此len-next[len],就是重复的那个子串的长度。这里要注意,如果字符串是“abcabcab”的话,字符串并不能被这个子串完美表示,因此要用len%(len-next[len]) 验证一下,要是==0,就是完美表示且len-next[len]是最小循环节,否则就没有。

    3、求一个字符串所有前缀字符和后缀字符匹配的长度:

    (给出一个字符串S,长度为len;找出一个前缀一个后缀,使得这两个字符串相同。 输出所有可能的情况)

    前面不是讲了那个len-next[len] 是最小的循环节嘛,那你想哦,s[1] -- s[next[len]] 跟 s[len-next[len]+1] -- s[len] 一定是匹配的。所以一个是头,一个就是尾吖。

    这样求出的s[1]——s[next[len]]就是我们要求取的最长的那个串,长度是:next[len] 。然后然后,要求所有的话,我们循环地利用next,由于next的性质,可以保证,每一次得出的字串都能匹配到最后一个字母,也就是得到一个前缀等于后缀。只不过这个字符串的长度在不断地减小罢了。不断地使用next我们直到求出所有的前缀。

    4、NEXT 求最长前缀后缀子串长度

    题目:https://www.cnblogs.com/767355675hutaishi/p/4425987.html

     1 int next[100] ;
     2 int nextt[10005];
     3 int n,m;
     4 string a,b;
     5 
     6 void getNext( )     {
     7     int len = a.size() ;
     8     next[0] = 0 ;
     9     int i = 0 , j = 0 ;
    10     for(j = 1 ; j < len ; j++) {                // i 代表最长前缀后缀长度
    11         while( a[i] != a[j] && i > 0  )          // 当p[i] != p[j] 时,减小最长前缀后缀长度
    12             i = next[i-1] ;
    13         if(a[i] == a[j])    {
    14             i++ ;                               //最长公共前缀后缀长度+1
    15             next[j] = i ;                       //匹配失败时跳到该处
    16         }
    17         else
    18             next[j] = 0 ;
    19     }
    20 }
    21 
    22 int main()  {
    23     cin>>a;
    24     int len =n= a.size(); ;
    25     getNext();
    26     len=next[len-1];
    27     while(len>0){
    28     b=a.substr(0,len);
    29     m=b.size();
    30     findnext();
    31     int x=kmp();
    32     if(x<=2)
    33         len--;
    34     else{
    35         cout<<b<<endl;break;}
    36     }
    37     if(len==0)
    38         printf("Just a legend
    ");
    39     return 0 ;
    40 }
    41 
    42 int main()  {
    43     cin>>a;
    44     int len =n= a.size(); ;
    45     getNext();
    46     len=next[len-1];
    47     return 0 ;
    48 }
    View Code

    ///////////////////////////////////////////////// 假装是条分割线 /////////////////////////////////////////////////////

    需要补充:

    字符串的最小表示/最大表示。

    まだまだだね
  • 相关阅读:
    java学习之旅(一):BOS项目使用的技术以及开发环境
    spring手动回滚
    tomcat下配置多端口,多项目
    centos7安装Mysql5.6
    windows phone7 下 Silverlight 异步读取网络图片
    Sencha Touch 本地化存储配置
    LCD1602显示接收的串口通讯字串
    QML 怎么在gridview中用Index定位? 怎么在代理中设置背景?
    89C52定时/计数器
    QML JSON 展示
  • 原文地址:https://www.cnblogs.com/xxQ-1999/p/7522424.html
Copyright © 2011-2022 走看看