zoukankan      html  css  js  c++  java
  • 【XSY2534】【CF835D】Palindromic characteristics 回文自动机

    题目大意

    ​  一个字符串(s)(1)−回文串当且仅当这个串是回文串。

    ​  一个串(s)(k)−回文串((k>1))当且仅当(s)的前一半与后一半相同且(s)的前一半是非空((k−1))−回文串。

    ​  一个串(s)的前一半是这个串的长度为(lfloorfrac{|s|}{2} floor)的前缀,一个串(s)的后一半是这个串的长度为(lfloorfrac{|s|}{2} floor)的后缀

    ​  有一个字符串(s),对于每个(kin{1ldots n}),求出(s)的多少个子串是(k)−回文串。

    ​  原题:(1leq nleq 5000)

    ​  加强版:(1leq nleq 1000000)

    题解

    ​  我们可以发现,一个串是(k)-回文串,那么这个串就是((k-1))-回文串((k>1))

    ​  所以可以DP:设(f_{i,j})表示(s_{ildots j})最高是几阶回文串

    ​  时间复杂度:(O(n^2))

    ​  我们还可以用BZOJ4044那道题的方法,在回文自动机上处理出每个串的长度不超过这个串长一半的最长回文后缀,然后直接转移即可

    ​  时间复杂度:(O(n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    int nxt[1000010][30];
    int fail[1000010];
    int len[1000010];
    int trans[1000010];
    int a[1000010];
    int f[1000010];
    int cnt[1000010];
    ll ans[1000010];
    int p;
    int n;
    int last;
    void init(int x)
    {
        int i;
        for(i=1;i<=26;i++)
            nxt[x][i]=2;
    }
    void add(int x)
    {
        a[++n]=x;
        while(a[n-len[last]-1]!=a[n])
            last=fail[last];
        int cur=last;
        if(nxt[cur][x]==2)
        {
            int now=++p;
            init(p);
            len[now]=len[cur]+2;
            last=fail[last];
            while(a[n-len[last]-1]!=a[n])
                last=fail[last];
            fail[now]=nxt[last][x];
            if(len[fail[now]]<=len[now]/2)//没有这部分也可以AC 
                trans[now]=fail[now];
            else
            {
                last=trans[cur];
                while(len[last]+2>len[now]/2||a[n-len[last]-1]!=a[n])
                    last=fail[last];
                trans[now]=nxt[last][x];
            }
            nxt[cur][x]=now;
        }
        last=nxt[cur][x];
        cnt[last]++;
    }
    void solve()
    {
        f[1]=0;
        f[2]=0;
        int i;
        for(i=3;i<=p;i++)
        	if(len[trans[i]]==len[i]/2)
    	    	f[i]=f[trans[i]]+1;
    	    else
    	    	f[i]=1;
        for(i=p;i>=3;i--)
        	cnt[fail[i]]+=cnt[i];
        for(i=3;i<=p;i++)
        	ans[f[i]]+=cnt[i];
    }
    char s[1000010];
    int main()
    {
    //  freopen("necklace.in","r",stdin);
    //  freopen("necklace.out","w",stdout);
        p=0;
        n=0;
        init(++p);
        fail[p]=2;
        len[p]=-1;
        trans[p]=2;
        init(++p);
        fail[p]=1;
        len[p]=0;
        a[0]=-1;
        trans[p]=1;
        last=p;
        int m;
        scanf("%s",s+1);
        m=strlen(s+1);
        int i;
        for(i=1;i<=m;i++)
            add(s[i]-'a'+1);
        solve();
        for(i=m-1;i>=1;i--)
        	ans[i]+=ans[i+1];
        for(i=1;i<=m;i++)
        	printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    JD笔试试题(凭记忆写的+人生感悟 try finally )
    ZOJ 3626 Treasure Hunt I(树形dp)
    Oracle数据库有用函数
    leetcode
    BIEE11G系统数据源账号过期问题(默认安装步骤)
    class文件结构浅析(2)
    使用Lua 局部变量来优化性能,同一时候比較局部变量和全局变量
    Linux基本配置和管理 3 ---- Linux命令行文本处理工具
    android面试题及答案
    CentOS 6.4的安装--史上最全-CRPER木木
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8510044.html
Copyright © 2011-2022 走看看