鬼题Ghost [manacher]
本题目来自five20的周末考试题。
Description
给定一个 0/1 序列,求其中满足 " ⺉ " 性质的子串个数。
" ⺉ " 性质解释:
" ⺉ " 性质的子串满足:将该子串先反转,再把每位上的数取反(即 0 变 1,1 变 0 )后得到的新串和原串相同。(举
例 : 1010 满足 " ⺉ " 性质,因为先变为 0101 ,再取反为 1010 和原串相同)
Input Format
第一行只含一个 n ,表示 0/1 序列⻓度。
第二行为⻓度为 n 的 0/1 序列。
Output Format
一个数,表示 0/1 序列中满足 " ⺉ " 性质的子序列个数(由于答案可能很大,对 233333333 取模)。
Sample
Input
7
1011001
Output
6
Explana on
样例中满足 " ⺉ " 性质的 6 个子序列分别是: 2 个 10 ,2 个 01 ,1 个 1100 ,1 个 011001 。Subtasks
因为题目可能过于毒瘤,如果无法完全解决问题,可以尝试解决部分子任务。
测试点 N
1 N ≤ 1000
2 N ≤ 1000
3 N ≤ 1000
4 N ≤ 1000
5 N ≤ 10000
6 N ≤ 10000
7 N ≤ 10000
8 N ≤ 10000
9 N = 520520
10 N = 520520
11 N = 520520
12 N = 520520
13 N = 2333333
14 N = 2333333
15 N = 2333333
16 N = 2333333
17 N = 6666666
18 N = 6666666
19 N = 10000000
20 N = 10000000
分析:当时考试的时候还以为这是什么数位DP的问题(而且当时也没学manacher,也不太擅长字符串算法什么的),由于蒟蒻真的不擅长DP于是就打了个暴力水了25分,然后考完five20大佬说这是manacher算法题。然后今天学了一下manacher,A了这道题。实际上仔细分析这道题比一般的manacher还要简单一些,把判断条件改为不等,那么这样连中间的插入字符都不需要了,直接一个for循环套个manacher主体就过了。
Code:
//It is made by HolseLee on 30th Apr 2018 //five20's test #include<bits/stdc++.h> using namespace std; const int mod=233333333; const int N=1e7+7; long long n,ans,p[N];char s[N]; int main() { freopen("ghost.in","r",stdin); freopen("ghost.out","w",stdout); scanf("%lld%s",&n,s+1);long long id,mx=0; for(int i=1;i<=n;i++){ if(i<mx)p[i]=min(p[id*2-i],mx-i); while(i+p[i]+1<=n&&i-p[i]>=1&&s[i+p[i]+1]!=s[i-p[i]])p[i]++; if(p[i]+i>mx)id=i,mx=p[i]+i; ans=(ans+p[i])%mod;} printf("%lld",ans);return 0; }
如需转载,请署名作者并附上原文链接,蒟蒻非常感激
名称:HolseLee
博客地址:www.cnblogs.com/cytus
个人邮箱:1073133650@qq.com