poj 2752 seek the name,seek the fame【KMP】

http://poj.org/problem?id=2752

題意:找出所給串的所有前綴長度,使得所給串中這個長度的前綴==這個長度的後綴

Sample Input
ababcababababcabab
aaaaa

Sample Output
2 4 9 18
1 2 3 4 5


看了HDU 1686 Oulipohttp://972169909-qq-com.iteye.com/blog/1070507
相信next值的意義就很清晰了

下面給出描述: (i>1)[下標從0開始]
next[i]的意義就是:前面長度爲i的字串的【前綴和後綴的最大匹配長度】

那麼這題怎麼利用這個性質呢?

詳細分析一下:【就用上面的第一個例子說明吧】
求出next值:[非修正]
下標:      0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17
串:          a  b  a  b  c  a  b  a  b  a  b   a   b   c   a   b   a   b
next值:  -1  0  0  1  2  0  1  2  3  4  3   4   3   4   5   6   7   8   9

len2 = 18    next[len2] = 9
說明對於前面長度爲18的字符串,【長度爲9的前綴】和【長度爲9的後綴】是匹配的, 即上圖的藍色跟紅色匹配
也就是整個串的最大前後綴匹配長度就是9了
所以接下來根本不需要考慮長度大於9的情況

好了!既然現在只需考慮長度小於9的前後綴匹配情況,那麼
[問題就轉化成藍色串的前綴紅色串的後綴的匹配問題了!!!
又因爲藍串==紅串
所以問題又轉化成
找藍串自己的前綴跟自己的後綴的最大匹配了!!!
那麼我們現在就要找next[9]的值了【next[9]的含義:藍串的最大前後綴匹配】

回憶第一步:我們找的是next[len2]=9【len2=18】
怎麼使得第二部目標變成9【求next[9]】呢?
其實next[len2]=9同時可以表示爲:最大匹配前後綴的【前綴長度
那麼next[9]的意義就是:
【主串】的最大匹配前後綴的【前綴】的【最大匹配前後綴】了!!
也就是上面藍串的前後綴最大匹配長度了!!

那麼算法描述就是:
第一步:求next[len2], 即next[18] = 9;
第二步:把9代進來,即求next[9] = 4;
第三步:把4代進來,即求next[4] = 2;
第四步:next[2] = 0; 也就是下標2之前的串已經沒有前後綴可以匹配了
所以答案就是: 2 4 9 18 【PS: 從小到大輸出,18是串長,顯然符合題意】
局部實現代碼:

C++代碼 複製代碼 收藏代碼
  1. #include <iostream>   
  2. #include <stdio.h>   
  3. #include <stdlib.h>   
  4. #include <string.h>   
  5. #include <math.h>   
  6. #include <algorithm>   
  7. using namespace std;   
  8. #define L2 400005   
  9.   
  10. int next[L2], len2, ans[L2];   
  11. char p[L2];   
  12. bool hash[L2];   
  13.   
  14. void get_next()   
  15. {   
  16.     int k = -1, j = 0;   
  17.     next[0] = -1;   
  18.     while (j < len2)   
  19.     {   
  20.         if (k == -1 || p[j] == p[k])   
  21.         {   
  22.             j++, k++;   
  23.             next[j] = k;   
  24.         }   
  25.         else k = next[k];   
  26.     }   
  27. }   
  28.   
  29. int main()   
  30. {   
  31.     int k, i, j;   
  32.     while (scanf ("%s", p) != EOF)   
  33.     {   
  34.         k = 0;   
  35.         memset (hash, falsesizeof(hash));   
  36.         len2 = strlen (p);   
  37.         get_next();   
  38.         j = next[len2];   
  39.         while (j > 0)   
  40.             ans[k++] = j, j = next[j];   
  41.         for (i = k - 1; i >= 0; i--)        //倒過來輸出,就是從小到大了   
  42.             printf ("%d ", ans[i]);   
  43.         printf ("%d\n", len2);   
  44.     }   
  45.     return 0;   
  46. }  
發佈了82 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章