zoukankan      html  css  js  c++  java
  • [JSOI2013]快乐的 JYY

    题意:

    洛谷链接

    题面很啰嗦,大致意思就是:给你两个字符串 (S,T),求有多少对 (S) 的子串和 (T) 的子串是相同的字符串且是回文串。

    输入:PUPPY PUPPUP

    输出:17


    额,manacher傻乎乎的,没法解决回文串出现次数这类的问题,所以我们用 (PAM)

    其实很简单,不要想太多。

    (PAM) 的每一个点表示一个本质不同的回文串,那么我们如果知道这个串在 (S) 中的出现次数和在 (T) 中的出现次数乘起来就是这个串的答案。

    那么我们将两个字符串分别建一个 (PAM) ,统计答案时将两个 (PAM) 同时遍历,保证遍历的两个位置表示的是同一个串,如果有任何一个没有往下走的路:(ch[x][i]==0 || ch[y][i]==0),那么就找别的路,因为有一个字符串中没有相应的回文串那么以后更长的回文串也不可能产生贡献了。

    由于奇数长度的回文树和偶数长度的回文树独立且互不交叉,所以分别遍历一遍,将所有乘积加起来即为答案。

    怎样统计出现次数,只需要沿着 (fail) 树从深到浅拓扑就行了,因为 (fail) 树上的点是按相同的右端点连接的,将同一个右端点最长的回文串开始将所有回文串次数加一,可以保证不重不漏。

    遇到要建两个或者多个 (PAM) 的题,用结构体真香。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define QWQ cout<<"QwQ"<<endl;
    #define ll long long
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    using namespace std;
    const int N=101010;
    const int qwq=303030;
    const int inf=0x3f3f3f3f;
    
    ll ans;
    
    struct PAM{
    	int n;
    	char s[N];
    	int now,cnt=1;
    	int len[N],ch[N][26],fail[N];
    	ll siz[N];
    
    	int getfail(int i,int x) {
    		while(s[i-len[x]-1] != s[i]) x = fail[x];
    		return x;
    	}
    
    	void built() {
    		n = strlen(s+1);
    		len[1] = -1; fail[0] = 1;
    		s[0] = '#';
    		for(int i=1;i<=n;i++) {
    			int x = getfail(i,now), c = s[i]-'A';
    			if(!ch[x][c]) {
    				len[++cnt] = len[x] + 2;
    				fail[cnt] = ch[ getfail(i,fail[x]) ][c];
    				ch[x][c] = cnt;
    			}
    			now = ch[x][c];
    			siz[now]++;
    		}
    		for(int i=cnt;i>=2;i--)
    			siz[ fail[i] ] += siz[i];
    	}
    
    } P,Q;
    
    void DFS(int p,int q) {
    	if(p>1) ans += P.siz[p] * Q.siz[q];
    	for(int i=0;i<26;i++)
    		if(P.ch[p][i] && Q.ch[q][i])
    			DFS(P.ch[p][i],Q.ch[q][i]);
    }
    
    int main() {
    	scanf("%s",P.s+1); P.built();
    	scanf("%s",Q.s+1); Q.built();
    	DFS(1,1);
    	DFS(0,0);
    	cout<<ans;
    	return 0;
    }
    
    
    

    首先记得 (0) 号点和 (1) 号点是不能算入贡献的。

    然后要记得开(long long)。。。

  • 相关阅读:
    MySQL锁之一:锁详解
    eclipse maven plugin 插件 安装 和 配置
    火星坐标系统
    使用Spring MVC统一异常处理实战
    websocket之二:WebSocket编程入门
    spring mvc 异常统一处理方式
    Android面向HTTP协议发送post请求
    用JAX-WS在Tomcat中公布WebService
    css3 -&gt; 多栏布局
    NSLayoutConstraint-代码实现自己主动布局的函数使用方法说明
  • 原文地址:https://www.cnblogs.com/clever-sheep/p/12797945.html
Copyright © 2011-2022 走看看