标签:
2 abc abaadada
Yes No
大致题意:
判断长度为2e4的字符串是否能分割成三个回文串
大致思路:
BC由于做出了这题,拿到钱了2333
Manacher处理出回文串区间, 然后得到两个数组a,b分别表示:字符0位置到a[pos]是回文串,字符len-1位置到b[pos]是回文串
然后折半枚举判a[x]~b[y]是不是回文串,用manacherO(1)就能判出来
Manacher算出了已s[x]为中心的最长回文串,然后反推到原串上的区间比较麻烦
以前推了一个公式,已经用这个公式过了三题了,说明的确没问题
int L = (i-Mp[i])>>1;
int R = (i+Mp[i]-4)>>1;
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <cstdio> #include <ctime> #include <bitset> #include <algorithm> #define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end() #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i) #define REP(i,n) for ( int i=1; i<=int(n); i++ ) using namespace std; typedef long long ll; #define X first #define Y second typedef pair<int,int> pii; template <class T> inline bool RD(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void PT(T x){ if (x < 0) { putchar('-'); x = -x; } if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } const int N = 20000+100; int a[N],top1; int b[N],top2; char s[N]; void ini(){ top1 = 0; top2 = 0; } int Mp[N<<1]; char Ma[N<<1]; int vs[N]; void Manacher(char s[],int len) { int l = 0; Ma[l++] = '$'; Ma[l++] = '#'; for(int i=0;i<len;i++){ Ma[l] = s[i]; vs[i] = l++; //记录映射到原串中的位置 Ma[l++] = '#'; } Ma[l] = 0; int mx = 0,id = 0; for(int i = 1;i < l ;i ++){ Mp[i]= mx>i? min(Mp[2*id-i],mx-i) :1; while(Ma[Mp[i]+i ] == Ma[i-Mp[i] ]) Mp[i]++; if(Mp[i]+i > mx){ mx = Mp[i]+i; id = i; } if( Mp[i] >= 2){ int L = (i-Mp[i])>>1; //逆推到原串中的区间左端点 int R = (i+Mp[i]-4)>>1; //逆推到原串中的区间右端点 if(L == 0) a[++top1] = R; if(R == len-1) b[++top2] = L; } } } int main(){ int T; RD(T); while(T--){ scanf("%s",s); ini(); int len = strlen(s); Manacher(s,len); sort(a+1,a+1+top1); sort(b+1,b+1+top2); bool ok = 0; REP(i,top1) { if(ok) break; for(int j = top2; j >= 1 && ok == 0;j--){ int l = a[i], r = b[j]; if( r-l <= 1) break; l++,r--; if( (r-l+1)&1 ){ int pos = l+(r-l+1)/2; int L = (vs[pos]-Mp[vs[pos]])>>1; int R = (vs[pos]+Mp[vs[pos]]-4)>>1; if( L <= l && r <= R) ok = 1; } else { int pos = l+(r-l+1)/2; int p = vs[pos]-1; if( Mp[p] < 2) continue; int L = (p-Mp[p])>>1; int R = (p+Mp[p]-4)>>1; if( L <= l && r <= R) ok = 1; } } } if(ok) puts("Yes"); else puts("No"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5340 Three Palindromes( 折半枚举+Manacher+记录区间 )
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/47210305