URAL 1297 Palindrome
2014-03-04 19:43
239 查看
一道比较简单的利用后缀数组的题目。(当然,利用其他字符串算法也能做)
思路比较简单,也比较好实现。
记原串为A,将原串倒过来变成A',将这两个字符串接起来,当然中间要加上分隔符。
那么,这时候两个串对应的后缀的最大公共前缀就有可能是回文子串(为什么要加上可能?因为这里面会有两个后缀的前缀是不是对应的问题。)。
思路比较简单,也比较好实现。
记原串为A,将原串倒过来变成A',将这两个字符串接起来,当然中间要加上分隔符。
那么,这时候两个串对应的后缀的最大公共前缀就有可能是回文子串(为什么要加上可能?因为这里面会有两个后缀的前缀是不是对应的问题。)。
#include<cstdio> #include<cstring> using namespace std; const int nMax = 2222; int num[nMax]; int sa[nMax], rank[nMax], height[nMax]; int wa[nMax], wb[nMax], wv[nMax], wd[nMax]; int cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a+l] == r[b+l]; } int min(int a,int b){return a<b ? a:b;} int max(int a,int b){return a>b ? a:b;} void da(int *r, int n, int m){ // 倍增算法 r为待匹配数组 n为总长度 m为字符范围 int i, j, p, *x = wa, *y = wb, *t; for(i = 0; i < m; i ++) wd[i] = 0; for(i = 0; i < n; i ++) wd[x[i]=r[i]] ++; for(i = 1; i < m; i ++) wd[i] += wd[i-1]; for(i = n-1; i >= 0; i --) sa[-- wd[x[i]]] = i; for(j = 1, p = 1; p < n; j *= 2, m = p){ 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 < n; i ++) wv[i] = x[y[i]]; for(i = 0; i < m; i ++) wd[i] = 0; for(i = 0; i < n; i ++) wd[wv[i]] ++; for(i = 1; i < m; i ++) wd[i] += wd[i-1]; for(i = n-1; i >= 0; i --) sa[-- wd[wv[i]]] = y[i]; for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i ++){ x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p - 1: p ++; } } } void calHeight(int *r, int n){ // 求height数组。 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 ++); } } char s[2222]; int main(){ scanf("%s",s); int len=(int)strlen(s); s[len]='$'; for(int i=0;i<len;i++) s[len+1+i]=s[len-1-i]; //for(int i=0;i<2*len+1;i++) printf("%c",s[i]); //printf("\n"); int n=2*len+1; for(int i=0;i<n;i++) num[i]=s[i]; num =0; da(num,n+1,130); calHeight(num,n); int ans=1; int loc=0; int low,high; for(int i=2;i<=n;i++){ if(height[i]>=ans){ if((sa[i-1]-len)*(sa[i]-len)<0){ low=min(sa[i-1],sa[i]); high=max(sa[i-1],sa[i]); if((low+high+height[i])==n){ if(height[i]>ans){ ans=height[i]; loc=low; }else{ loc=min(loc,low); } } } } } for(int i=0;i<ans;i++) printf("%c",s[i+loc]); printf("\n"); return 0; }
相关文章推荐
- 【后缀数组】【最长回文子串】Palindrome Ural_1297
- URAL 1297 Palindrome (后缀数组+RMQ)
- URAL 1297 Palindrome <后缀数组+RMQ>
- ural 1297Palindrome(求最长回文)
- URAL 1297 Palindrome
- URAL 1297 Palindrome【后缀数组】求最长回文子串
- URAL 1297 Palindrome(SA 求最长回文子串)
- ural1297 . Palindrome
- ural 1297 Palindrome(后缀数组)
- URAL1297-Palindrome
- Palindrome URAL - 1297
- URAL 1297 Palindrome (最长回文子串)
- Ural 1297 Palindrome (后缀数组)
- 【ural1297】Palindrome 后缀数组
- URAL 1297 - Palindrome(最长回文 后缀数组)
- URAL 1297 Palindrome
- URAL1297:Palindrome(后缀数组)
- 【ural1297】 Palindrome
- Palindrome - URAL - 1297(求回文串)
- Ural1297 Palindrome(后缀数组)