zoukankan      html  css  js  c++  java
  • P5404-[CTS2019]重复【KMP,dp】

    正题

    题目链接:https://www.luogu.com.cn/problem/P5404


    题目大意

    给出一个字符串(S),然后求有多少个长度为(m)的串(T)满足。无限多个串(T)拼接起来后能找出一个长度和(S)相等的子串字典序比(S)小。

    (1leq |S|,mleq 2000)


    解题思路

    首先有一个小于的很难找,所以我们找有多少一直大于等于的减去就好了。

    然后其实如果有一个大于位置大于(S)串匹配就可以直接不管,所以其实我们主要考虑前面都相等的情况,(根据题解)考虑用(KMP)

    设我们现在匹配到([1,k]),然后有([1,nxt_k]=[k-nxt_k+1,k]),然后加了一个字符如果有跳的边而且是转移边里面字符最大的,因为我们显然需要匹配出一个最大的前缀不然不能保证有小于的时候能直接找到。

    而且如果我们现在在(KMP)上走了(T^{infty})之后节点是(i),那么(T^{infty}T)也是会匹配回到节点(i)的,所以相当于我们要找一个节点(p)使得它匹配了(T)之后仍然是回到节点(p)

    暴力枚举节点来(dp)肯定是会(T),考虑优化一下。

    不难发现如果一个点走(m)步之后没有回到过(0)号节点的话方案只有一种(因为每个点连接(0)以外的出边最多只有一条)。

    所以设(f_{i,j})表示从(0)出发走(j)步到达(i)的方案数。

    然后对于起点枚举多少步后走到(0)再用(f)统计答案就好了。

    时间复杂度(O(nm))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=2100,P=998244353;
    ll n,m,ans,nxt[N],ch[N][26],f[N][N],mx[N];
    char s[N];
    signed main()
    {
    	scanf("%lld%s",&m,s+1);
    	n=strlen(s+1);ans=1;
    	for(ll i=1;i<=m;i++)ans=ans*26ll%P;
    	for(ll i=2,j=0;i<=n;i++){
    		while(j&&s[i]!=s[j+1])j=nxt[j];
    		j+=(s[i]==s[j+1]);nxt[i]=j;
    	}
    	for(ll i=0;i<=n;i++)
    		for(ll c=0;c<26;c++){
    			if(s[i+1]==c+'a')ch[i][c]=i+1;
    			else ch[i][c]=ch[nxt[i]][c];
    			if(ch[i][c])mx[i]=c; 
    		}
    	f[0][0]=1;
    	for(ll i=0;i<m;i++)
    		for(ll j=0;j<=n;j++)
    			for(ll c=mx[j];c<26;c++)
    				(f[ch[j][c]][i+1]+=f[j][i])%=P;
    	for(ll i=0;i<=n;i++){
    		ll x=i;
    		for(ll j=1;j<=m;j++){
    			(ans-=(25-mx[x])*f[i][m-j]%P)%=P;
    			x=ch[x][mx[x]];
    			if(!x)break;
    		}
    		if(i&&x==i)(ans+=P-1)%=P;
    	}
    	printf("%lld
    ",(ans+P)%P);
    	return 0;
    }
    
  • 相关阅读:
    复杂业务
    重析业务逻辑架构模式
    Katana介绍以及使用
    使用ServiceStack构建Web服务
    ASP.NET vNext 在 Mac OS
    用户端的防腐层作用及设计
    Mvc 模块化开发
    编程语言
    页面生命周期
    If you pay peanuts,you get monkeys
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14978300.html
Copyright © 2011-2022 走看看