zoukankan      html  css  js  c++  java
  • LOJ#2452. 「POI2010」反对称 Antisymmetry

    题目链接

    48分做法

    枚举每个子串,用 hash 逐一判断是否为反对称字符串。

    时间复杂度为 (mathcal O(n^2)),而此题 (nle 5 imes 10^5),只能得到 (48) 分。

    100分做法

    观察到 (n) 的数据范围,可知此题的复杂度要在 (mathcal O(nlog n)) 及以下。于是,不难想到二分。

    不难得出,每个反对称字符串的长度一定是偶数,这样我们就可以枚举每个字符串中间的空隙(中轴),然后二分配合 hash 求中轴为 (l) 的最长反对称字符串长度 (l),每次 (mathrm{ans}) 加上 (l/2) 就是最终答案。这是因为,如果一个串 (s) 为反对称字符串,那么 (s) 所有以 (l) 为中轴的子串都是反对称字符串,这样的子串共 (l/2) 个。可以自己模拟一下试试。实际实现中,二分的是 (l/2),这样更方便一些。

    可以配合图理解一下:

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int N=5e5,base=1e9+7;
    char s[N+10];
    ull h1[N+10],h2[N+10],p[N+10];
    bool t1[N+10],t2[N+10];
    int n; 
    void init()
    {
    	p[0]=1ull;
    	for(int i=1;i<=n;i++) p[i]=p[i-1]*base;
    	for(int i=1;i<=n;i++) h1[i]=h1[i-1]*base+(s[i]=='1');
    	for(int i=1;i<=n;i++) h2[i]=h2[i-1]*base+(s[n-i+1]=='0');
    }
    ull hs(ull *h,int l,int r) {return h[r]-h[l-1]*p[r-l+1];}
    bool check(int l,int r) {return hs(h1,l,r)==hs(h2,n-r+1,n-l+1);}
    int erfen(int i)
    {
    	int l=0,r=min(i,n-i),ans=0;
    	while(l<=r)
    	{
    		int mid=(l+r)/2;
    		if(check(i-mid+1,i+mid)) 
    		{
    			l=mid+1;
    			ans=mid;
    		} 
    		else r=mid-1;
    	}
    	return ans;
    }
    int main()
    {
    	ll ans=0;
    	scanf("%d%s",&n,s+1); 
    	init();
    	for(int i=1;i<n;i++) ans+=erfen(i);
    	printf("%lld",ans);
    	return 0;
    }
    

    据说马拉车 Manacher 也能做?但我不会。。

  • 相关阅读:
    esp8266(3) Arduino通过ESP8266连接和获取网站源代码
    esp8266(2) 智能配置
    图像工程考试
    Arduino IDE for ESP8266 ()esp8266项目 WIFI攻击器
    esp8266(1) 手机+Arduino+esp8266通信
    esp8266(0) AT指令
    ROS ZED
    手机APP
    Arduino IDE for ESP8266教程(0)配置IDE
    Arduino 433 + 串口
  • 原文地址:https://www.cnblogs.com/juruo-zzt/p/13290430.html
Copyright © 2011-2022 走看看