鬼题Ghost [manacher]

  本题目来自five20的周末考试题。c++

  

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主体就过了。spa

  Code: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;
}
相关文章
相关标签/搜索