51Nod - 1304 :字符串的相似度 (裸的擴展KMP)
阿新 • • 發佈:2018-06-03
字母 前綴 scan length clas str input printf while
我們定義2個字符串的相似度等於兩個串的相同前綴的長度。例如 "abc" 同 "abd" 的相似度為2,"aaa" 同 "aaab" 的相似度為3。
給出一個字符串S,計算S同他所有後綴的相似度之和。例如:S = "ababaa",所有後綴為: ababaa 6 babaa 0 abaa 3 baa 0 aa 1 a 1 S同所有後綴的相似度的和 = 6 + 0 + 3 + 0 + 1 + 1 = 11Input輸入一個字符串S(1 <= L <= 1000000),L為字符串S的長度,且S由a-z的小寫字母組成。Output輸出S同所有後綴的相似度的和。Sample Input
ababaa
Sample Output
11
: KMP可以求S串以i結尾的後綴與T串的前綴最長公共串長度。
: 擴展KMP可以求S串以i為起點的的後綴與T串的前綴的最長公共字串。
此題就是求所有i的擴展KMP長度;
以前學過,已經忘得差不多了。這裏再抄一發。
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int N = 1001010; int next[N],extand[N]; charS[N]; long long ans; void getnext(){ int i,length=strlen(S+1); next[1]=length; for(i=0;i+1<length&&S[i+1]==S[i+2];i++); next[2]=i; int a=2; for(int k=3;k<=length;k++){ int p=a+next[a]-1, L=next[k-a+1]; if(L>=p-k+1){int j=(p-k+1)>0?(p-k+1):0; while(k+j<=length&&S[k+j]==S[j+1]) j++; next[k]=j, a=k; } else next[k]=L; } for(int i=1;i<=length;i++) ans+=next[i]; printf("%lld\n",ans); } int main(){ scanf("%s",S+1); getnext(); return 0; }
51Nod - 1304 :字符串的相似度 (裸的擴展KMP)