Description
PCY学生物学累了。突然看到地上有一本笔记本。
上面写着“isdashagaydashisorosdashnot...”之类的字眼,独具慧眼的他发现这些字符串中有着大秘密!类似“isdash”这样的前缀在字符串中出现的次数不止一次!他觉得这其中一定有蹊跷,于是开始一个一个数前缀出现的次数。
虽然他早已经从逐字符匹配转换到了多行同时匹配模式,但是这小小的练习本上几十万个字符还是让他措手不及。你能帮助他吗?他想知道所有长度为偶数的前缀在整个字符串出现的次数和。
Input
共一行,一个字符串s。
Output
共一行,输出一个整数,代表长度为偶数的前缀在整个字符串出现的次数和。
Solution
KMP + DP,考虑 KMP 中的 next[i],
代表最大的 k(k!=i) 使‘s[1]s[2]…s[k]==s[i–k+1]s[i–k]…s[i]’,
那么我们设f[i]代表以i前缀‘s[1]s[2]…s[i]’内所有偶数子串出现的次数(包含本身),
得到:
时间复杂度 O(n)
代码
1 var 2 l,ans:longint; 3 s:ansistring; 4 next,f:array [0..200001] of longint; 5 procedure main; 6 var 7 i,j:longint; 8 begin 9 j:=0; l:=length(s); 10 for i:=2 to l do 11 begin 12 while (j>0) and (s[j+1]<>s[i]) do 13 j:=next[j]; 14 if s[j+1]=s[i] then j:=j+1; 15 next[i]:=j; 16 end; 17 fillchar(f,sizeof(f),0); 18 ans:=0; 19 for i:=2 to l do 20 begin 21 if i mod 2=0 then f[i]:=f[i]+1; 22 f[i]:=f[i]+f[next[i]]; 23 ans:=ans+f[i]; 24 end; 25 writeln(ans); 26 end; 27 28 begin 29 readln(s); 30 main; 31 end.