• bzoj3676-回文串


    给出一个字符串,一个子串的出现值为字串出现次数乘以长度,求所有回文串中最大的出现值。

    分析

    回文自动机模版题,建出自动机后直接统计即可。

    回文自动机

    类似于后缀自动机,不过一条边((u,v,c))的含义是在(u)点的串左右两边加上字母(c)可以得到(v)点代表的串。它的(fail)指针和AC自动机类似。这里有一个重要的简化代码,就是开始时设两个点,(len)长度分别为0和-1,两个点的fail指针互相指对方,这样可以保证奇数长度回文串长度从1开始,直接-1+2即可。fail往前跳的时候一定能够跳到0号点或1号点。这种写法还是很好的。

    代码

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long giant;
    int read() {
    	int x=0,f=1;
    	char c=getchar();
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    const int maxn=3e5+1;
    const int maxc=26;
    struct PAM {
    	int s[maxn],n,t[maxn][maxc],len[maxn],link[maxn],cnt[maxn],last,tot;
    	PAM () {
    		last=tot=1;
    		s[n=0]=-1;
    		len[0]=0,len[1]=-1;
    		link[0]=1,link[1]=0;
    	}
    	int fail(int x) {
    		for (;s[n-len[x]-1]!=s[n];x=link[x]);
    		return x;
    	}
    	void add(int x) {
    		s[++n]=x;
    		last=fail(last);
    		if (!t[last][x]) {
    			int nw=++tot;
    			len[nw]=len[last]+2;
    			link[nw]=t[fail(link[last])][x];
    			t[last][x]=nw;
    		}
    		++cnt[last=t[last][x]];
    	}
    	giant run() {
    		giant ans=0;
    		for (int i=tot;i>1;--i) cnt[link[i]]+=cnt[i],ans=max(ans,(giant)cnt[i]*len[i]);		
    		return ans;
    	}
    } pam;
    char s[maxn];
    int main() {
    	#ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    	#endif
    	scanf("%s",s+1);
    	int n=strlen(s+1);
    	for (int i=1;i<=n;++i) pam.add(s[i]-'a');
    	printf("%lld
    ",pam.run());
    	return 0;
    }
    
  • 相关阅读:
    python3数据库配置,远程连接mysql服务器
    Ubuntu 16.04安装JDK
    用Python从零开始创建区块链
    理解奇异值分解SVD和潜在语义索引LSI(Latent Semantic Indexing)
    gensim介绍(翻译)
    记一次浅拷贝的错误
    Heap queue algorithm
    Python
    python列表中插入字符串使用+号
    Linux(Ubuntu)使用 sudo apt-get install 命令安装软件的目录在哪?
  • 原文地址:https://www.cnblogs.com/owenyu/p/6724648.html
Copyright © 2020-2023  润新知