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

    luogu

    题目大意

    对于字符串 \(S\) 的前 \(i\) 个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作 num[i]。例如 \(S\)aaaaa,则num[4]=2 num[4] = 2 num[4]=2。这是因为 \(S\) 的前 \(4\) 个字符为 aaaa,其中 aaa 都满足性质‘既是后缀又是前缀’,同时保证这个后缀与这个前缀不重叠。而 aaa 虽然满足性质‘既是后缀又是前缀’,但遗憾的是这个后缀与这个前缀重叠了,所以不能计算在内。
    字符串长度 \(L \le 10^6\), 多组数据 \(T \le 5\)

    /*
    观察:
    nxt[i]: 字符串有前i个字符构成的的前缀最长的相等的真前缀和真后缀的长度 (嵌套的!)(真前/后缀:与原串不相等的前/后缀)
    num[i]:字符串前i个字符不重叠的相等前后缀数量
    
    注意到对于s[1..i]: s[1..nxt[i]], s[1..nxt[nxt[i]]], s[1..nxt[nxt[nxt[i]]]], ... 是s[1..i]的全部的相等前后缀
    所以只需要不断跳nxt[i]直到不重叠即可
    */
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    const int maxn = 1e6 + 5;
    const int mod = 1e9 + 7;
    
    char a[maxn];
    int nxt[maxn]; // KMP的nxt
    int v[maxn]; // v[i]是前i个字符的前缀的前缀和后缀相同的个数(嵌套的)
    
    int mul(int x, int y) {
    	return static_cast<long long>(x) * y % mod;
    }
    
    int main() {
    	int T;
    	scanf("%d", &T);
    	for (int _ = 0; _ < T; ++_) {
    		scanf("%s", a + 1);
    		int n = strlen(a + 1);
    
    		int j = 0;
    		v[1] = 1; // 初始时,只有1个字符,此时它自己的前缀和后缀都可以是它自己,故为1
    		for (int i = 2; i <= n; ++i) {
    			while (j > 0 && a[j + 1] != a[i]) {
    				j = nxt[j];
    			}
    			j += a[j + 1] == a[i];
    
    			nxt[i] = j;
    			v[i] = v[j] + 1; // 递推,1是前缀i自己的贡献(一个字符串本身既是自己的前缀,又是自己的后缀)
    		}
    
    		j = 0;
    		int r = 1;
    		for (int i = 2; i <= n; ++i) {
    			while (j > 0 && a[j + 1] != a[i]) {
    				j = nxt[j];
    			}
    			j += a[j + 1] == a[i];
    
    			// 题目要求前缀和后缀没有重叠部分
    			// 这里j就是最大前缀(后缀)长度
    			// 前后缀长度都为j,总共为2*j,而没有重叠部分要求i>=j*2
    			// 当j*2>i时,通过j=nxt[j]缩短长度
    			while (j * 2 > i) {
    				j = nxt[j];
    			}
    
    			// 此时j长度合适,那么题目所求的num[i]显然是v[j]
    			r = mul(r, v[j] + 1); // 注意题目要求+1
    		}
    		printf("%d\n", r);
    	}
    	return 0;
    }
    
  • 相关阅读:
    谈谈泛型和锁,一个值得注意的问题!
    关于++运算符重载的一个问题,有点“饶”!
    关于抽象类的构造函数!
    在嵌套类中是否可以触发外部类中定义的事件!
    谈谈C#的私有成员的一个有趣的现象!
    关于循环引用!
    谈谈常数字段!
    C#中对byte类型的处理。
    C#l编译器是否会为值类型生成默认的构造函数!
    谈谈DivideByZeroException异常!并非像表面那么简单!
  • 原文地址:https://www.cnblogs.com/szdytom/p/15576369.html
Copyright © 2011-2022 走看看