zoukankan      html  css  js  c++  java
  • [NOI2014]动物园

    Description

    Luogu2375

    Solution

    KMP神题。
    首先注意到这个题一定要考KMP,所以先做一遍KMP再说。然后仔细观察就可以发现,在不管前后缀是否相交的情况下,(ans[i] = ans[next[i]] + 1),这里加上的那个(1)是前后缀都是原串的情况。然后怎么处理前后缀不相交呢,一个简单的思路就是让(next[i] < i / 2)就好了。但是如果在做KMP的时候判掉这个会导致之后的转移不对,在KMP之后暴力的跳也会导致TLE。于是我们观察发现:如果(next[i] > i / 2)的话,那么(next[i] + 1 > (i+1) / 2)显然成立。所以在跳第一下的时候是可以跳到满足(next[i-1] < (i-1) / 2)(next[i-1])的。(这里还是看代码吧,不大好用文字描述)。然后就可以做两边KMP,第一遍是正常的KMP,第二遍要求(Next[i] < i / 2),这样的话,(num[i] = ans[Next[i]])

    Code

    #include <cstdio>
    #include <cstring>
    
    const int N = 1e6 + 10;
    typedef long long LL;
    const LL MOD = 1e9 + 7;
    
    char s[N];
    int nxt[N], cnt[N], Nxt[N];
    /*nxt是正常的next数组,Nxt是要求Nxt[i] < i / 2的next数组*/
    LL ans, len;
    
    void work1() {
    	for (int i = 1; i <= len; ++i) {
    		int t = nxt[i - 1];
    		while (t != -1 && s[t+1] != s[i]) t = nxt[t];
    		nxt[i] = t+1; 
    		cnt[i] = cnt[t+1] + 1;
    	}
    }
    
    void work2() {
    	for (int i = 1; i <= len; ++i) {
    		int t = Nxt[i-1];
    		if (t + 1 > i / 2) t = nxt[t];
    		while (t != -1 && s[t+1] != s[i]) t = nxt[t];
    		Nxt[i] = t+1;
    	}
    }
    
    int main() {
    	int t;
    	scanf("%d", &t);
    	while (t--) {
    		scanf("%s", s+1);
    		len = strlen(s+1);
    		Nxt[0] = nxt[0] = -1;
    		work1();
    		work2();
    		ans = 1;
    		for (int i = 1; i <= len; ++i) ans = ans * (cnt[Nxt[i]] + 1) % MOD;
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    

    Note

    做了这个题我忽然发现我的KMP还没有后缀数组掌握的好,真不知道我一直在学啥。

  • 相关阅读:
    function to_timestamp(timestamp without time zone, unknown) does not exist
    Xshell连接不上Ubuntu解决方式
    怎样使用MobaXterm上传文件到远程Linux系统 MobaXterm怎么使用连接远程服务器?
    notepad++怎样删除空行
    思维脑图在线制作工具网址
    @ApiImplicitParams
    .bat批出处理文件
    主题模型及其在文本情感分析中的应用
    表达式求职JAVA(转)
    2013华为校园招聘java实现(大家水个回复啊)
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/noi2014zoo.html
Copyright © 2011-2022 走看看