其实这也是一道水题。。自已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 1000005
using 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);
}
}
本文介绍了一种结合KMP算法与树形DP的方法来解决字符串匹配问题。通过构造特殊的next数组,并利用DFS遍历的方式,实现了O(N)的时间复杂度。文中详细解释了算法流程,包括KMP预处理、构建图结构以及深度优先搜索计算节点深度。
2188

被折叠的 条评论
为什么被折叠?



