Gym10198-Mediocre String Problem-2018南京ICPC現場賽
阿新 • • 發佈:2018-12-31
目錄
(有任何問題歡迎留言或私聊 && 歡迎交流討論哦
Catalog
@
Problem:傳送門
原題目描述在最下面。
Solution:
- 二分+\(hash\)+\(manacher\)
- 題意要我們在s串中找一個子串,和在t串中找一個字首串,組合成迴文串,但是串1長度要大於串2的長度。
- 其實就是要找三個串,在s中找連續的串a和串b,在t中找一個字首串c
- 滿足b是迴文串且長度至少為1,a串和c串對稱
- 到這一步思路就十分明確了,可以用\(manacher\)預處理出以\(i\)點為左端點的串是迴文串的個數,差分一下就可以了。
- 然後就很簡單了,先把t串反轉。
- 列舉\(i\)
AC_Code:
#include<bits/stdc++.h> #define lson rt<<1 #define rson rt<<1|1 #define fi first #define se second #define lowbit(x) (x&(-(x))) #define mme(a,b) memset((a),(b),sizeof((a))) #define fuck(x) cout<<"* "<<x<<"\n" #define iis std::ios::sync_with_stdio(false) using namespace std; typedef long long LL; const int N = 1e6+7; const int MXN = 1e6+7; const long long MOD = 2078526727; const long long BASE = 1572872831; LL pw[MXN], hs1[MXN], hs2[MXN]; int n, m; char ar[N<<1], br[N<<1], t[N]; int p[N<<1], pre[N]; void manacher(){ int Len = strlen(ar), id = 0, ans_id = 0, right = 0; memset(p, 0, sizeof(p)); memset(br, 0, sizeof(br)); for(int i = Len; i >= 0; --i){ ar[2 * i + 1] = '#'; ar[2 * i + 2] = ar[i]; } ar[0] = '*';p[0] = p[1] = 1; for(int i = 2; i < 2 * Len + 1; ++i){ if(i < right)p[i] = min(p[2 * id - i], right - i); else p[i] = 1; while(i - p[i] >= 0 && ar[i + p[i]] == ar[i - p[i]])p[i]++; if(p[ans_id] < p[i])ans_id = i; if(i + p[i] > right){ id =i; right = i + p[i]; } } } LL get(LL *a, int l, int r) { return ((a[r]-a[l-1]*pw[r-l+1])%MOD+MOD)%MOD; } bool ok(int len, int P, int lent) { if(get(hs1, P-len+1, P) == get(hs2, lent-len+1, lent)) return true; return false; } int main() { pw[0] = 1; for(int i = 1; i < 1000003; ++i) pw[i] = pw[i-1] * BASE % MOD; scanf("%s%s", ar, t); int len = strlen(ar); hs1[0] = hs2[0] = 1; for(int i = 0; i < len; ++i) { hs1[i+1] = (hs1[i]*BASE + ar[i]) % MOD; } manacher(); for(int i = 2; i < 2 * len + 1; ++ i) { pre[(i-p[i]+2)/2-1] ++; pre[i/2] --; //printf("%d %d %d %d\n", i, p[i], (i-p[i]+2)/2-1, i/2); } for(int i = 1; i < len; ++i) { pre[i] += pre[i-1]; } /*for(int i = 0; i < len; ++i) { printf("%d ", pre[i]); } printf("\n");*/ int lent = strlen(t); reverse(t, t + lent); for(int i = 0; i < lent; ++i) { hs2[i+1] = (hs2[i]*BASE + t[i]) % MOD; } int k = 0; for(int i = 2; i < 2*len-1; ++i) { if(i%2 == 0) ar[k++] = ar[i]; } LL res = 0; for(int i = 0; i < len - 1; ++i) { //二分LCP,[?,i],[1,?] if(ar[i] != t[lent-1]) continue; int l = 1, r = min(lent, i+1), mid, ans = 0; while(r >= l) { mid = (l+r)>>1; if(ok(mid, i+1, lent)) ans = mid, l = mid+1; else r = mid-1; } res += (LL)ans * pre[i+1]; //printf("%d %d\n", i, ans); } printf("%lld\n", res); return 0; }