[BZOJ3670]NOI2014动物园|KMP

来源:互联网 发布:linux yes命令 编辑:程序博客网 时间:2024/04/30 08:41

  其实这也是一道水题。。自已yy完之后思路乱的要死就挂了。。
  先求正常的next数组嘛,然后next[i]向i连边,容易发现新next在i到1的路径上,且i往下走,后面点新next也会往下走,然后我们从1 dfs下去,把路径上的点记录下来,然后维护一个新next指针作为参数,由于新next是不会往上爬的所以这是O(N)的,num[i]的话显然等于新next[i]在树上的深度+1,然后就做完了。。

#include<cstdio>#include<iostream>#include<cstring>#define p 1000000007#define N 1000005using namespace std;struct edge{    int e,next;}ed[N];char s[N];int n,i,len,ans,ne,next[N],a[N],num[N],to[N],d[N];void add(int s,int e){    ed[++ne].e=e;ed[ne].next=a[s];a[s]=ne;}void kmp(){    next[1]=0;add(0,1);    int j=0,k;    for (int i=2;i<=len;i++)    {        while (s[i]!=s[j+1]&&j>0) j=next[j];        if (s[i]==s[j+1]) j++;        next[i]=j;add(j,i);    }}void dfs(int x,int last,int dd){    if (x)          while (to[last]*2<=x) last=to[last];    d[x]=dd;    if (x)ans=((long long)ans*(d[last]+1))%p;    for (int j=a[x];j;j=ed[j].next)        to[x]=ed[j].e,dfs(ed[j].e,last,dd+1);}int main(){    freopen("zoo.in","r",stdin);    scanf("%d",&n);    while (n--)    {        scanf("%s",s+1);        len=strlen(s+1);ne=0;        for (i=0;i<=len;i++) a[i]=0;        ans=1;kmp();        dfs(0,0,0);        printf("%d\n",ans);    }}
0 0