zoukankan      html  css  js  c++  java
  • BZOJ2084[Poi2010]Antisymmetry——回文自动机

    题目描述

    对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。
    现在给出一个长度为N的01字符串,求它有多少个子串是反对称的。

    输入

    第一行一个正整数N (N <= 500,000)。第二行一个长度为N的01字符串。

    输出

    一个正整数,表示反对称子串的个数。

    样例输入

    8
    11001011

    样例输出

    7
    hint
    7个反对称子串分别是:01(出现两次), 10(出现两次), 0101, 1100和001011
     
    对于一个回文串我们判定的方法是对称的位置字符相同,而反对称串则是要求对称的位置字符不同,所以在建回文自动机跳$fail$时只要将判断条件改一下即可。因为反对称串长度一定是偶数,所以不必建出奇回文树(当跳到$1$时就停止)。剩下的就是查询子串数了,一个点所代表的反对称串被所有$fail$指针直接或间接指向它的点所代表的反对称串包含,所以只需要求每个点在$fail$树上的子树权值和即可(因为回文自动机上每个点所代表的的回文串在原串中不一定出现一次,所以每个点的权值不同)。
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<bitset>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    char s[500010];
    int fail[500010];
    int tr[500010][26];
    int len[500010];
    int n,p,q;
    int last;
    int cnt[500010];
    int num;
    ll ans;
    int build(int x)
    {
    	len[++num]=x;
    	return num;
    }
    int main()
    {
    	scanf("%d",&n);
    	scanf("%s",s+1);
    	fail[0]=1,len[1]=-1,num=1;
    	for(int i=1;i<=n;i++)
    	{
    		int x=s[i]-'a';
    		p=last;
    		while((s[i-len[p]-1]==s[i]||i-len[p]-1==0)&&p!=1)
    		{
    			p=fail[p];
    		}
    		if(s[i-len[p]-1]==s[i]||i-len[p]-1==0)
    		{
    			last=0;
    			continue;
    		}
    		if(!tr[p][x])
    		{
    			q=build(len[p]+2);
    			int np;
    			np=fail[p];
    			while((s[i-len[np]-1]==s[i]||i-len[np]-1==0)&&np!=1)
    			{
    				np=fail[np];
    			}
    			if(s[i-len[np]-1]==s[i]||i-len[np]-1==0)
    			{
    				fail[q]=0;
    			}
    			else
    			{
    				fail[q]=tr[np][x];
    			}
    			tr[p][x]=q;
    		}
    		cnt[last=tr[p][x]]++;
    	}
    	for(int i=num;i>=1;i--)
    	{
    		cnt[fail[i]]+=cnt[i];
    		ans+=1ll*cnt[i];
    	}
    	printf("%lld",ans);
    }
  • 相关阅读:
    Spring Boot 中加载XML配置
    C#winfrom打开指定的文件
    C#怎么实现文件下载功能的四种方法
    C#查看已下载文件大小和扩展名
    C#winfrom文件下载到本地
    判断DataGridView是否选中某行
    Secure CRT注册码
    http-server 开启服
    学习网址
    angular中table表格组件的使用
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/10418027.html
Copyright © 2011-2022 走看看