Evanyou Blog 彩带

  本题目来自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;
}
原文地址:https://www.cnblogs.com/cytus/p/8974053.html