hdu 3068 and ural 1297
2013-01-22 22:18
267 查看
两道回文串的题目,关于回文串的题目有很多种解法。以前写回文串的题目都是采用后缀数组写的,今天无意中搜到了Manacher算法,就学了一下。发现Manacher算法真心简洁,复杂度低编程量低。后缀数组写起来得100来行的题目,Manacher写起来不到30行,无限ORZ。。。关于Manacher算法:http://wenku.baidu.com/view/3031d2d3360cba1aa811da42.html
直接看这里就明白了。不过这个文档上的提供的HDOJ3068的代码有点问题。比如数据:
aaaa
aaa
答案两个都是4,n值计算错误,应该为n = 1<<i就可以了。不过杭电的数据水了,将文档上提供的代码交上去竟然也过了。。。。。。hdu3068采用了比较快的getchar()读入后,也就跑了250ms,不知道那些跑了100+ms的是怎么写的,ORZ。。。。。。
hdu3068
ural 1297
后缀数组版:
直接看这里就明白了。不过这个文档上的提供的HDOJ3068的代码有点问题。比如数据:
aaaa
aaa
答案两个都是4,n值计算错误,应该为n = 1<<i就可以了。不过杭电的数据水了,将文档上提供的代码交上去竟然也过了。。。。。。hdu3068采用了比较快的getchar()读入后,也就跑了250ms,不知道那些跑了100+ms的是怎么写的,ORZ。。。。。。
hdu3068
#include <stdio.h> #define L 110010 char a[L<<1]; int p[L<<1]; int min(int a, int b){ if(a < b) return a; return b; } int main(){ int i, n, id, MaxL, MaxId; char ch; while((ch=getchar())!=EOF){ n = 4; a[0] = '$', a[1] = '#'; a[2] = ch , a[3] = '#'; while((ch = getchar())!='\n'){ a[n ++] = ch, a[n ++] = '#'; } a = 0; MaxL = MaxId = 0; for(i = 1; i < n; i ++){ if(MaxId > i) p[i] = min(p[2*id - i], MaxId - i); else p[i] = 1; while(a[i+p[i]]==a[i-p[i]]) p[i] ++; if(p[i] + i > MaxId) MaxId = p[i] + i, id = i; if(p[i] > MaxL) MaxL = p[i] ; } printf("%d\n", MaxL - 1); } }
ural 1297
后缀数组版:
#include <cstdio> #include <cstring> #define maxn 2005 char s[maxn]; int r[maxn], sa[maxn], rank[maxn], height[maxn]; int wa[maxn], wb[maxn], wv[maxn], ws[maxn]; bool cmp(int *arr, int x, int y, int l){ return arr[x]==arr[y]&&arr[x+l]==arr[y+l]; } void da(int *r, int *sa, int n, int m){ int i, j, p, *x = wa, *y = wb, *t; for(i = 0; i < m; i ++) ws[i] = 0; for(i = 0; i < n; i ++) ws[x[i]=r[i]] ++; for(i = 1; i < m; i ++) ws[i] += ws[i-1]; for(i = n-1; i >= 0; i --) sa[--ws[x[i]]] = i; for(j = 1; j <= n; j<<=1){ for(p = 0, i = n - j; i < n; i ++) y[p ++] = i; for(i = 0; i < n; i ++) if(sa[i] >= j) y[p ++] = sa[i] - j; for(i = 0; i < m; i ++) ws[i] = 0; for(i = 0; i < n; i ++) ws[wv[i] = x[y[i]]] ++; for(i = 1; i < m; i ++) ws[i] += ws[i-1]; for(i = n-1; i >= 0; i --) sa[--ws[wv[i]]] = y[i]; t = x, x = y, y = t; p = 1, x[sa[0]] = 0; for(i = 1; i < n; i ++) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p - 1 : p ++; if(p >= n) break; m = p; } } void calcHeight(int *r, int *sa, int n){ int i, j, k = 0; for(i = 1; i <= n; i ++) rank[sa[i]] = i; for(i = 0; i < n; height[rank[i ++]] = k) for(k?k--:0, j = sa[rank[i]-1]; r[i+k]==r[j+k]; k ++); } int min(int x, int y){ return x < y ? x : y; } //mm[i] = log(i) int RMQ[maxn][15], mm[maxn]; void initRMQ(int n){ int i, j, a, b; for(mm[0] = -1, i = 1; i < maxn; i ++){ mm[i] = (i&(i-1)) == 0 ? mm[i-1] + 1 : mm[i-1]; } for(i = 1; i <= n; i ++) RMQ[i][0] = height[i]; for(j = 1; (1<<j) <= n; j ++) for(i = 1; i + (1<<j) - 1 <= n; i ++){ RMQ[i][j] = min(RMQ[i][j-1], RMQ[i+(1<<(j-1))][j-1]); } } int query(int a, int b){ int t = mm[b-a+1]; b = b - (1<<t) + 1; return min(RMQ[a][t], RMQ[b][t]); } int lcp(int a, int b){ a = rank[a], b = rank[b]; int t; if(a > b) t = a, a = b, b = t; return query(a + 1, b); } int main(){ int i, n, len, ans, tmp, loc; scanf("%s", s); len = strlen(s); for(i = 0; i < len; i ++) r[i] = s[i]; r[len] = 1; for(i = 0; i < len; i ++) r[i + len + 1] = s[len - i - 1]; n = len * 2 + 1; r = 0; da(r, sa, n + 1, 129); calcHeight(r, sa, n); initRMQ(n); ans = 0; loc = -1; for(i = 0; s[i]; i++){ tmp = lcp(i, n - i); if(ans < 2 * tmp) ans = 2 * tmp , loc = i - tmp; tmp = lcp(i, n - i- 1); if(ans < 2 * tmp - 1) ans = 2 * tmp - 1,loc = i - tmp + 1; } s[ans + loc] = 0; printf("%s\n", s+loc); return 0; }Manacher版
#include <stdio.h> #define M 2010 char a[M]; int p[M]; int min(int a,int b){ return a < b ? a : b; } int main(){ char ch; int i, n, id, MaxL, MaxId, loc; a[0] = '$', a[1] = '#', n = 2; while((ch=getchar())!='\n'){ a[n ++] = ch, a[n ++] = '#'; } MaxL = MaxId = 0, a = 0; for(i = 1; i < n; i ++){ if(i < MaxId) p[i] = min(p[2*id-i], MaxId - i); else p[i] = 1; while(a[i+p[i]] ==a[i-p[i]]) p[i]++; if(i+p[i] > MaxId) MaxId = i + p[i] , id = i; if(p[i] > MaxL) MaxL = p[i], loc = i; } for(i = loc - MaxL + 1; i < loc + MaxL; i ++) if(a[i]!='#') putchar(a[i]); }
相关文章推荐
- ural1297 Palindrome,hdu 3068 最长回文,Manacher
- 【HDU】 1029 Ignatius and the Princess IV
- hdu_5683_zxa and xor(非正解的暴力)
- hdu 5066 Harry And Physical Teacher(物理题 弹性碰撞)
- hdu 5564 Clarke and digits
- HDU 3046 Pleasant sheep and big big wolf(最小割)
- HDU 4297 One and One Story(图-最近公共祖先)
- hdu 5068 Harry And Math Teacher ( 线段树+矩阵乘法 )
- 排列-hdu_1027_Ignatius and the Princess II
- HDU 1848 Fibonacci again and again(博弈论:sg函数)
- HDU 1028 Ignatius and the Princess III
- HDU 5464 Clarke and problem 动态规划
- [Ural1297]Palindrome(后缀数组+RMQ)
- hdu 1297 Children’s Queue(找规律+高精度)
- hdu-1078-FatMouse and Cheese
- HDU 3911 Black And White
- hdu 3911 Black And White(线段树)
- hdu 4336 概率and数位DP
- HDU 4614 Vases and Flowers [二分 + 线段树]
- DFS-HDU 1312 -Red and Black