[NOI2014]动物园

来源:互联网 发布:中国国际贸易数据库 编辑:程序博客网 时间:2024/04/29 06:06

KMP好题

首先考虑那些可以成为前缀+后缀的子串(不考虑重叠)

发现从i跳到Next[i]时就找到一个子串

再考虑重叠问题,向前跳的过程中i在不断缩小,于是从i<<1 <= 当前长度起前面都是合法串

O(n)扫两遍

Code:

#include <cstdio>#include <cstring>#define N 1000001#define MOD 1000000007using namespace std;struct String{char c[N], ch;int p[N], l, i, j, num[N];inline void Init(){memset(p, 0, sizeof(p));memset(num, 0, sizeof(num));l = 0;for (ch = getchar();ch != '\n'; ch = getchar())c[++l] = ch;}inline void Next(){p[1] = j = 0;num[1] = 1;for (i = 2;i <= l; ++i){while (j && c[i] != c[j+1])j = p[j];p[i] = j += (c[i] == c[j+1]);num[i] = num[j] + 1;}  }inline void Debug(){j = 0;int res(1);for (i = 2;i <= l; ++i){while (j && c[i] != c[j+1])j = p[j];j += (c[i] == c[j+1]);while ((j << 1) > i)j = p[j];res = (long long)((long long)res * (long long)(num[j]+1)) % MOD;}printf("%d\n", res);}}B;int main(){int T;scanf("%d ", &T);while (T--){B.Init();B.Next();B.Debug();}return 0;}


0 0