zoukankan      html  css  js  c++  java
  • HDU5343 MZL's Circle Zhou (后缀自动机)

    HDU-5343 MZL's Circle Zhou (后缀自动机)

    题意:从\(A,B\)两串中各选出一个子串\(x,y\)(可以为空),求能构成的不同串的个数

    为了避免重复统计,我们需要规定优先级

    对于任意一个答案中的串,它的合法切分中,我们使得\(|x|\)最大

    对于\(A,B\)分别构建后缀自动机

    我们统计\(y\)串开头字符是\(c\)的合法方案数,就必须使得\(x\)不存在\(+c\)的转移,否则就意味着\(|x|\)不是最大的

    当然\(B\)要倒着建立自动机才能确定这些子串的开头字符

    注意一下统计空串的一些细节

    #include<bits/stdc++.h>
    using namespace std;
    
    #define reg register
    typedef long long ll;
    typedef unsigned long long ull;
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    
    #define pb push_back
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    
    char IO;
    template<class T=int> T rd(){
    	T s=0;
    	int f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=200000+10;
    
    int n;
    char A[N],B[N];
    int trans[N][26],link[N],len[N],lst,stcnt,End[N],ma[N];
    
    ull Sum[N],Ans;
    
    void Init(){
    	link[0]=-1,len[0]=0;
    	rep(i,0,stcnt) ma[i]=0,memset(trans[i],0,104);
    	stcnt=lst=0;
    }
    
    void Extend(int c) {
    	int cur=++stcnt,p=lst;
    	End[cur]=len[cur]=len[p]+1;
    	while(~p && !trans[p][c]) trans[p][c]=cur,p=link[p];
    	if(p==-1) link[cur]=0;
    	else {
    		int q=trans[p][c];
    		if(len[q]==len[p]+1) link[cur]=q;
    		else {
    			int clone=++stcnt;
    			End[clone]=End[q];
    			memcpy(trans[clone],trans[q],104);
    			len[clone]=len[p]+1,link[clone]=link[q];
    			while(~p && trans[p][c]==q) trans[p][c]=clone,p=link[p];
    			link[cur]=link[q]=clone;
    		}
    	}
    	lst=cur;
    }
    
    
    int main(){
    	rep(kase,1,rd()) {
    		scanf("%s%s",A+1,B+1);
    		Init();
    		rep(i,1,strlen(A+1)) Extend(A[i]-'a');
    		memset(Sum,0,sizeof Sum),Ans=0;
    		rep(i,1,stcnt) { 
    			Ans+=len[i]-len[link[i]];// 考虑y为空串
    			rep(j,0,25) if(!trans[i][j]) Sum[j]+=len[i]-len[link[i]]; // 如果不存在转移就累和
    		}
    		rep(i,0,25) if(!trans[0][i]) Sum[i]++; // 考虑x为空串
    		n=strlen(B+1);
    		Init();
    		drep(i,n,1) Extend(B[i]-'a'); // 要倒着建立自动机才能确定这些子串的开头字符
    		rep(i,1,stcnt) if(End[i]) Ans+=(len[i]-len[link[i]])*Sum[B[n-End[i]+1]-'a'];
    		Ans++;
    		printf("%llu\n",Ans);
    	}
    }
    
    
    
    
  • 相关阅读:
    第四次博客作业-结对项目
    软件工程第三次作业——关于软件质量保障初探
    java 自动生成四则运算式
    《构建之法》第一章学习笔记
    给大家分享一个小程序—2048
    Java异常处理认识
    轻松定位CPU飙高问题
    接手​「烂摊子」,管理者怎么办?
    业务中台建设篇
    互联网巨头“大中台,小前台”战略
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12216788.html
Copyright © 2011-2022 走看看