zoukankan      html  css  js  c++  java
  • [NOI2014]动物园 题解(预览)

    一开始读错题了淦。


    对于一个位置 (i)(num[i]) 显然是满足条件的最大前缀长 (k)(next[k]) 跳到 (0) 需要的次数。

    对每个 (i) 如何求 (k)? 类比 (next) 的递推方式, 只需要加个限制长度的 (while) 语句就可以求出 (k) 了。((i)(k)(i-1)(k) 推出即可,至于为什么,画一画qwq)

    如何计数一个位置 (s)(nxt) 跳到 (0) 的次数?可以发现若对于每个 (s),将 (nxt[s])(s) 连一条有向边, 所形成的结构就是一棵树, 其中, 入度为 (0) 的节点为 (0), 且 (s)(nxt) 跳到 (0) 需要跳的次数就是以 (0) 为根时 (s) 的深度。


    luogu数据AC代码

    #include<bits/stdc++.h>
    using namespace std;
    #define li long long
    const int maxn = 1e6+5;
    const int mod = 1000000007;
    
    int len, nxx[maxn], nxt[maxn];
    char s[maxn];
    
    int ct, hed[maxn], nx[maxn<<1], ver[maxn<<1];
    void ad(int a,int b) {
    	ver[++ct] = b;
    	nx[ct] = hed[a];
    	hed[a] = ct;
    }
    int dep[maxn];
    void dfs(int x,int Dep) {
    	dep[x]=Dep;
    	for(int i=hed[x];i;i=nx[i]) {
    		int y=ver[i];
    		dfs(y,Dep+1);
    	}
    }
    
    int main()
    {
    	int n; cin>>n; while(n--) {
    		ct = 0;
    		memset(hed,0,sizeof hed);
    		scanf("%s", s+1); len=strlen(s+1);
    		nxt[1]=0;
    		for(int i=2,j=0;i<=len;++i) {
    			while(j&&s[j+1]!=s[i]) j=nxt[j];
    			if(s[j+1]==s[i]) ++j;
    			nxt[i]=j;
    		}
    		nxx[1]=0;
    		for(int i=2,j=0;i<=len;++i) {
    			while(j+1>i/2) j=nxt[j];
    			while(j&&s[j+1]!=s[i]) j=nxt[j];
    			if(s[j+1]==s[i]) ++j;
    			nxx[i]=j;
    		}
    		//
    		for(int i=1;i<=len;++i) ad(nxt[i],i);
    		dfs(0,1);
    		li ans = 1ll;
    		for(int i=1;i<=len;++i) ans = ans*1ll*dep[nxx[i]]%mod;
    		cout<<ans<<'
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    JDBC 复习4 批量执行SQL
    JDBC 复习3 存取Oracle大数据 clob blob
    Oracle复习
    Linux命令(1)grep
    JDBC 复习2 存取mysql 大数据
    JDBC 复习1 DBUtil
    php 环境搭建问题
    Windows 批处理 bat 开启 WiFi 菜单选项 设置ID PWD
    Bat 批处理启动和停止Oracle 服务
    docker 学习1 WSL docker ,Windows docker
  • 原文地址:https://www.cnblogs.com/tztqwq/p/12799722.html
Copyright © 2011-2022 走看看