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;
    }
    
  • 相关阅读:
    css
    css笔记
    css笔记
    echarts
    css笔记
    跨域
    JS案例
    html2canvas
    echarts
    echarts
  • 原文地址:https://www.cnblogs.com/tztqwq/p/12799722.html
Copyright © 2011-2022 走看看