九度 1528:最长回文子串
回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。
回文子串,顾名思义,即字符串中满足回文性质的子串。
给出一个只由小写英文字符a,b,c...x,y,z组成的字符串,请输出其中最长的回文子串的长度。
思路
1. 使用枚举法判断, 时间复杂度会到 o(n^3)
2. 动规的记忆化搜索, 时间复杂度会降到 o(n^2)
3. leetcode 给出了一个算法, 将时间复杂度降低到 o(n)
代码
#include <iostream> #include <stdio.h> #include <cstring> using namespace std; char ori[200010]; char ist[500020]; int dist[500020]; int main() { while(scanf("%s", ori) != EOF) { int len = strlen(ori); int cur = 0; ist[cur++] = '^'; ist[cur++] = '#'; for(int i = 0; i < len; i ++) { ist[cur++] = ori[i]; ist[cur++] = '#'; } ist[cur++] = '$'; ist[cur] = '\0'; int ct = 1, rx = 0; // center, range int len2 = strlen(ist); memset(dist, 0, len2*4+5); for(int i = 1; i < len2-1; i ++) { int mirror = 2*ct - i; dist[i] = rx > i? min(rx-i, dist[mirror]):0; while(i+dist[i]+1 < len2 && i-dist[i]-1 >= 0 && ist[i+dist[i]+1] == ist[i-dist[i]-1]) dist[i] ++; if(i+dist[i] > rx) { ct = i; rx = i+dist[i]; } } int rev = 0; for(int i = 1; i < len2-1; i ++) { rev = max(rev, dist[i]); } cout << rev << endl; } return 0; }