POJ 2752 Seek the Name, Seek the Fame(KMP的next陣列)
阿新 • • 發佈:2018-11-01
【連結】http://poj.org/problem?id=2752
【題意】給個字串,求這個串所有字首與字尾相同的所有綴長度
【思路】
其實kmp裡的next這個微妙的陣列本身就是答案了,至於為什麼,我是用以前不知道哪裡弄來的的kmp模板試了一下看出來的【喂
從next陣列的最後一個值起往前找,只要next[i]的值不是-1,就說明s[0]~s[i]這個串有滿足本題條件的綴,綴的長度為next[i]+1(下標從0),記錄這個綴
下一步i=next[i],即從綴裡找綴,將原來的綴作為字串,按上面的步驟繼續找,直到next[i] == 0
……樣例君它是這樣的:
① ababcababababcabab(整個字串),next[17]=8,說明長度9是一個答案,即綴1=字首=字尾=ababcabab
② ababcabab(①中的綴),next[8]=3,說明長度4是一個答案,即綴2=字首=字尾=abab
③ abab,next[3]=1,說明長度2是一個答案,即綴3=字首=字尾=ab
④ ab,next[1]=-1,找不出綴了,停~
⑤ 加上原來的字串一整個作為字首也作為字尾的答案,所有的就是了
【程式碼】……本想把printArray這種羞澀的巨集去掉的不過好吧好吧既然用上了就放著吧……
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <iostream> #include <map> #include <vector> #include <set> #include <queue> #include <stack> #include <algorithm> using namespace std; #define MAX_LEN 400005 #define ll long long #define mod 100000007 #define MEM(a,al) memset(a,al,sizeof(a)) #define sfx(x) scanf("%lf",&x) #define sfxy(x,y) scanf("%lf%lf",&x,&y) #define sdx(x) scanf("%d",&x) #define sdxy(x,y) scanf("%d%d",&x,&y) #define pfx(x) printf("%.0f\n",x) #define pfxy(x,y) printf("%.6f %.6f\n",x,y) #define pdx(x) printf("%d\n",x) #define pdxy(x,y) printf("%d %d\n",x,y) #define getArray(a,len) for(int ia = 0; ia < len; ia++) scanf("%d",&a[ia]) #define printArray(a,len) for(int ia = 0; ia < len; ia++) printf("%d%c",a[ia],(ia==len-1)?'\n':' ') #define fora(i,n) for(i = 0; i < n; i++) #define fora1(i,n) for(i = 1; i <= n; i++) #define foraf(i,n) for(int i = 0; i < n; i++) #define foraf1(i,n) for(int i = 1; i <= n; i++) #define ford(i,n) for(i = n-1; i >= 0; i--) #define ford1(i,n) for(i = n; i > 0; i--) #define fordf(i,n) for(int i = n-1; i >= 0; i--) #define fordf1(i,n) for(int i = n; i > 0; i--) class WriteInfo{ public: void info() { printf("[Info] "); } void infoEnd() { printf(" [/Info]\n"); } } W; const int INF = 1<<29; const double INFD = 1e20; const double eps = 1e-6; int n,m,len; char s[MAX_LEN]; int next[MAX_LEN]; int res[MAX_LEN]; void getNext(){ MEM(next,-1); int j = -1; foraf1(i, len-1){ while(j > -1 && s[i] != s[j+1]) j = next[j]; if (s[i] == s[j+1]) j++; next[i] = j; } } int main() { int i,j,k; int T; while(scanf("%s",s) != EOF){ len = strlen(s); getNext(); i = len-1; j = 0; while(next[i] != -1){ res[j++] = next[i]+1; i = next[i]; } // 本身也符合字首等於字尾,都是自己 res[j++] = len; sort(res,res+j); printArray(res,j); } return 0; }
第一篇部落格就是kmp這種意義不明的東西,一定會成為黑歷史的……