题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6629
题意求字符串的每个后缀与原串的最长公共前缀之和。
比赛时搞东搞西的,还搞了个后缀数组...队友一说扩展kmp我都自闭了,这不就是扩展kmp的第一步,求原串的每个后缀与原串的最长公共前缀嘛。
需要注意的就是题目准确问的是按照文中所给的代码执行需要判断几次,如果最长公共前缀等于该后缀的长度,则会判断Next[i]次(Next[i]为以i为开始的后缀与原串的最长公共前缀)。如果不等,则会判断Next[i]+1次,因为会判断一次失配。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 using namespace std; 7 typedef long long ll; 8 const int maxn = 1e6 + 10; 9 int Next[maxn]; 10 void getN(char *s1) {//求子串与自身匹配 11 int i = 0, j, p, len = strlen(s1); 12 Next[0] = len; 13 while (i + 1 < len&&s1[i] == s1[i + 1]) 14 i++; 15 Next[1] = i; 16 p = 1; 17 for (i = 2; i < len; i++) { 18 if (Next[i - p] + i < Next[p] + p) 19 Next[i] = Next[i - p]; 20 else { 21 j = Next[p] + p - i; 22 if (j < 0) 23 j = 0; 24 while (i + j < len&&s1[j] == s1[i + j]) 25 j++; 26 Next[i] = j; 27 p = i; 28 } 29 } 30 } 31 char s[maxn]; 32 int main() { 33 int t; 34 scanf("%d", &t); 35 while (t--) { 36 scanf("%s", s); 37 int n = strlen(s); 38 getN(s); 39 long long ans = 0; 40 for (int i = 1; i < n; ++i) { 41 if (Next[i] == n - i) ans += n - i; 42 else ans += Next[i] + 1; 43 } 44 printf("%lld ", ans); 45 46 } 47 }