KMP补充:
next【i】表示 1--i 的最长后缀等于前缀
next【next【i】】 表示 1--i 的次长后缀等于前缀
题解:每个i 枚举所有next【i】 next【next【i】】。。。。。求小于长度 i/2 的个数
强行枚举next 50分
因为next【i】一定小于 i
所以建next【i】为 i 的爸爸 ,形成一个有根树,求每个节点的祖先有多少个小于i/2
我用栈加二分做 O(N *log N)
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
//int num[1000001];
int next[2000001];
struct node
{
int next;
int to;
};
node bian[2000001];
int first[2000001];
int tt;
int stack[2000001];
char c[2000001];
int tail,size;
long long ans;
void inser(int a,int b)
{
size++;
bian[size].next=first[a];
bian[size].to=b;
first[a]=size;
}
void dfs(int x)
{
int l,r,mid;
if(x!=0)
{
l=0;
r=tail+1;
while(r-l>1)
{
mid=(r+l)>>1;
if(stack[mid]<=(x>>1)) l=mid;
else r=mid;
}
// num[x]=r;
ans=(ans*l)%1000000007;
}
stack[++tail]=x;
for(int i=first[x];i;i=bian[i].next)
{
int u=bian[i].to;
dfs(u);
}
tail--;
}
int main()
{
int _q=5*(10<<20);
char *_p=(char*)malloc(_q)+_q;
__asm__("movl %0, %%esp\n"::"r"(_p));
//freopen("zoo.in","r",stdin);
// freopen("zoo.out","w",stdout);
int i,j,k;
scanf("%d\n",&tt);
while(tt)
{
tt--;
// memset(num,0,sizeof(num));
memset(first,0,sizeof(first));
size=0;
next[0]=-1;
gets(c+1);
n=strlen(c+1);
for(i=1;i<n;i++)
{
for(j=next[i];j!=-1;j=next[j])
if(c[i+1]==c[j+1]) break;
next[i+1]=j+1;
}
for(i=1;i<=n;i++)
inser(next[i],i);
ans=1;
tail=0;
// tail=1;
// stack[1]=0;
dfs(0);
cout<<ans;
if(tt) cout<<endl;
}
return 0;
}