• KMP


    http://acm.hdu.edu.cn/showproblem.php?pid=3336 


    题意:求字串中【前缀+跟前缀相同的子串】的个数? 

    Sample Input 


    abab 

    Sample Output 


    abab:包括2个a,2个ab,1个aba,1个abab
     

    这里要用到next值的意义: 
    next[i]表示前i个字符所组成的字符串最大前后缀匹配长度 
    举个例子: 
     
    next[5]=2, 表示下标5前面那个字符串abcab的前后缀匹配的最大长度是2,显然就是ab了 

    回到本题: 
    所求=字串的前缀个数+与前缀相同的子串 
    问题可以部分转化为:每个前缀的最大前后缀匹配问题 

    继续用上面的例子: 

    第一步: 
     
    对于这段子串,next[5]=2,然后后面不符合next值的递推规律了 
    所以对于abcab,长度为2的后缀,即ab与前缀匹配 
    所以+1个ab,注意还要+1个a,既然后缀ab跟前缀ab匹配,则必有a跟前缀匹配 
    也就是+2个了,其实实际上+next[5]就可以了,因为这是最长前后缀匹配长度 

    第二步: 
     
    对于这段子串: 
    next[6]=1,然后后面不符合next值的递推规律了 
    所以对于abcaba,长度为1的后缀,即a与前缀匹配 
    所以+1个a,也就是+next[6]了 

    第三步: 
     
    对于整个串: 
    next[12]=4后面没有了 
    所以对于整个串:abcabacbabca,长度为4的后缀跟前缀匹配 
    所以+1个abca,+1个abc,+1个ab,+1个a,总共+4个,也就是+next[12]了 

    最后: 
    好了,刚刚一共+了7个与前缀匹配的子串 
    上面说了题目是求:字串的前缀个数+与前缀相同的子串个数 
    与前缀相同的子串个数就是7个了 
    然后字串的前缀个数当然就是整个串的长度了,那么就是12个 
    加起来就是答案:19 



    核心实现代码: 

    C++代码  收藏代码
    1. res = next[len2] + len2;    //先包含:最后的next值【第三步】+前缀数【串长】  
    2. for (j = 0; j < len2; j++)  
    3.     if (next[j] > 0 && next[j] + 1 != next[j+1])  
    4.         res += next[j];    //当不满足递推规律时+next值【第一、二步】  



    C++代码  收藏代码
      1. #include <iostream>  
      2. #include <fstream>  
      3. #include <algorithm>  
      4. #include <string>  
      5. #include <set>  
      6. //#include <map>  
      7. #include <queue>  
      8. #include <utility>  
      9. #include <iomanip>  
      10. #include <stack>  
      11. #include <list>  
      12. #include <vector>  
      13. #include <cstdio>  
      14. #include <cstdlib>  
      15. #include <cstring>  
      16. #include <cmath>  
      17. #include <ctime>  
      18. #include <ctype.h>  
      19. using namespace std;  
      20. #define L2 200005  
      21.   
      22. int next[L2], len2;  
      23. char p[L2];  
      24.   
      25. void get_next ()    //KMP原始next值  
      26. {  
      27.     int j = 0, k = -1;  
      28.     next[0] = -1;  
      29.     while (j < len2)  
      30.     {  
      31.         if (k == -1 || p[j] == p[k])  
      32.         {  
      33.             j++, k++;  
      34.             next[j] = k;  
      35.         }  
      36.         else k = next[k];  
      37.     }  
      38. }  
      39. int main()  
      40. {  
      41.     int t, res, j;  
      42.     scanf ("%d", &t);  
      43.     while (t--)  
      44.     {  
      45.         scanf ("%d%s", &len2, p);  
      46.         get_next ();  
      47.         res = next[len2] + len2;  
      48.         for (j = 0; j < len2; j++)  
      49.             if (next[j] > 0 && next[j] + 1 != next[j+1])  
      50.                 res += next[j];  
      51.         printf ("%d\n", res%10007);  
      52.     }  
      53.     return 0;  
      54. }  

    原文转自:http://972169909-qq-com.iteye.com/blog/1114968

  • 相关阅读:
    linux分区
    MySQL
    RGB中的颜色的设置
    解决UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 12: ordinal not in range(128)的编码问题
    解决运行scrapy是报错No module named cryptography,解决cryptography的安装问题,解决libffi的安装问题
    解决pycharm下安装reportLab报错的问题
    简单的爬取并下载图片的程序
    linux常用命令
    ubuntu下安装pycharm的方法
    win7下装ubuntu双系统后无法进入win7的解决方法
  • 原文地址:https://www.cnblogs.com/10jschen/p/2649576.html
Copyright © 2020-2023  润新知