回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。
输入一个字符串Str,输出Str里最长回文子串的长度。
Input
输入Str(Str的长度 <= 1000(第二题要求为100000))
Output
输出最长回文子串的长度L。
Input示例
daabaac
Output示例
5
解:
1 #include <stdio.h> 2 3 int main() 4 { 5 char s[1005]; 6 while (scanf_s("%s", s, 1005) != EOF) 7 { 8 int max = 0; 9 for (int i = 0, j, a; s[i] != 0; i++) 10 { 11 for (j = 0; j <= i; j++) 12 if (s[i + j + 1] != s[i - j - 1])break; 13 a = j * 2 + 1; 14 max = a > max ? a : max; 15 for (j = 0; j <= i; j++) 16 if (s[i + 1 + j] != s[i - j]) 17 break; 18 a = j * 2; 19 max = a > max ? a : max; 20 } 21 printf("%d\n", max); 22 } 23 }
后来找了一些其他的解法,比较著名的是Manacher算法,它通过插入“#”的方式将我程序中的两类讨论变为了一种情况,避免了分类讨论,同时也优化了寻找过程。
Manacher实现:
1 //1089 最长回文子串 V2(Manacher算法) 2 #include <stdio.h> 3 #include <string.h> 4 #define CLR(x,len) memset(x, '#', len) 5 6 char s1[100005], s2[200005]; 7 int p[200005]; 8 9 int main() 10 { 11 while (scanf_s("%s", s1, 100005) != EOF) 12 { 13 int dis = 0, st = 0, i, len = (strlen(s1) << 1) + 1, ans = 0; 14 CLR(s2, len); 15 s2[len] = 0; 16 for (i = 0; s1[i] != 0; i++) s2[i << 1 | 1] = s1[i]; 17 i = 1; 18 for (int temp ; i < len; i++) 19 { 20 if (i < dis) p[i] = p[(st << 1) - i] > dis - i ? dis - i : p[(st << 1) - i]; 21 else p[i] = 0; 22 while (i - p[i] > 0 && s2[i + 1 + p[i]] == s2[i - 1 - p[i]]) p[i]++; 23 if (p[i] + i > dis) 24 { 25 dis = p[i] + i; 26 st = i; 27 } 28 if (s2[i + p[i]] != '#') temp = 1; 29 else temp = 0; 30 ans = ans > p[i] + temp ? ans : p[i] + temp; 31 } 32 printf("%d\n", ans); 33 } 34 }