[BZOJ4566]-[Haoi2016]找相同字符-后缀自动姬上的统计问题

xiaoxiao2021-02-28  28

说在前面

免得me某一天愚蠢到了连这道题都不会做 于是还是记录下来


题目

BZOJ4566传送门

题面

给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两 个子串中有一个位置不同

输入输出格式

输入格式: 输入仅两行,每行包含一个字符串

输出格式: 输出一行一个整数,表示答案


解法

好像做法还挺多的… me想的是统计每一个子串的贡献,于是对这两个串建一个 广义后缀自动姬(别被吓到了…只是建在一起而已) 然后每个节点维护cnt1和cnt2,第一个串主链的cnt1为1,第二个串主链cnt2为1,逆拓扑序累加上去 那么,对于自动姬上的每个节点,贡献就是 (lenp.len)cnt1cnt2 ( l e n − p . l e n ) ∗ c n t 1 ∗ c n t 2 ,即当前节点长度 * 从1选的方案数 * 从2选的方案数


下面是自带大常数的代码

#include <map> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; long long ans ; char ss[200005] ; int len , tp , head[800006] , id_c ; struct Node{ int cnt[2] , len , id ; map<int,Node*> ch ; Node *par ; } *root , *las , w[800005] , *tw = w ; struct Path{ int pre , to ; }p[800005] ; void newNode( Node *&nd , int len ){ nd = ++ tw ; nd->len = len ; nd->id = ++id_c ; } void Insert( int id , bool cate ){ Node *nd , *tmp = las ; newNode( nd , las->len + 1 ) ; nd->cnt[cate] = 1 ; for( ; tmp && !tmp->ch.count( id ) ; tmp = tmp->par ) tmp->ch[id] = nd ; if( !tmp ) nd->par = root ; else{ Node *B = tmp->ch[id] ; if( B->len == tmp->len + 1 ) nd->par = B ; else{ Node *nB ; newNode( nB , tmp->len + 1 ) ; nB->par = B->par ; nd->par = B->par = nB ; nB->ch = B->ch ; while( tmp && tmp->ch[id] == B ) tmp->ch[id] = nB , tmp = tmp->par ; } } las = nd ; } void dfs( int &u ){ Node *nd = w + u ; for( int i = head[u] , v ; i ; i = p[i].pre ){ v = p[i].to ; dfs( v ) ; nd->cnt[0] += w[v].cnt[0] ; nd->cnt[1] += w[v].cnt[1] ; } if( u != 1 ) ans += 1LL * nd->cnt[0] * nd->cnt[1] * ( nd->len - nd->par->len ) ; } void solve(){ for( int i = 2 ; i <= id_c ; i ++ ){ p[++tp] = ( Path ){ head[ w[i].par->id ] , i } ; head[ w[i].par->id ] = tp ; } dfs( id_c = 1 ) ; printf( "%lld" , ans ) ; } int main(){ newNode( root , 0 ) ; root->par = NULL ; las = root ; scanf( "%s" , ss ) ; len = strlen( ss ) ; for( int i = 0 ; i < len ; i ++ ) Insert( ss[i] - 'a' , 0 ) ; las = root ; scanf( "%s" , ss ) ; len = strlen( ss ) ; for( int i = 0 ; i < len ; i ++ ) Insert( ss[i] - 'a' , 1 ) ; solve() ; }
转载请注明原文地址: https://www.6miu.com/read-2632219.html

最新回复(0)