本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:codeforces291E
正解:哈希+倍增
解题报告:
突然发现我似乎搞复杂了…
不管了,先讲一讲我的做法好了。
因为字符最多只有$3*10^5$个,那么把字符拆成一个个点,构出一张新图,又因为题目中有限制,必须是一条从上往下的路径,
所以对于每个点都考虑以当前点为结尾的字符串是否与要求的相同,这个的话$hash$就可以了,
然后取出一段祖先区间就用倍增维护好了。
做法暴力,好写好想…
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> #include <bitset> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 600011; const int MAXM = 1200011; const int mod = 52013147; const int base = 29; int n,m,tot,ecnt,father[MAXN],first[MAXN],to[MAXM],next[MAXM],f[MAXN][20],deep[MAXN],ans; LL mo[MAXN],g[MAXN][20],Ha; char s[MAXN]; inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void init(){ mo[0]=1; for(int i=1;i<=600000;i++) mo[i]=mo[i-1]*base,mo[i]%=mod; for(int j=1;j<=19;j++) for(int i=1;i<=tot;i++) { f[i][j]=f[f[i][j-1]][j-1]; g[i][j]=( g[i][j-1]*mo[(1<<(j-1))] + g[f[i][j-1]][j-1] )%mod; } } inline bool check(int x){ LL now=0; int remain=m; for(int i=19;i>=0;i--) if(remain>=(1<<i)) now=(now*mo[(1<<i)]+g[x][i])%mod,x=f[x][i],remain-=(1<<i); if(now==Ha) return true; return false; } inline void dfs(int x,int fa){ if(deep[x]>=m) { if(check(x)) ans++; } for(int i=first[x];i;i=next[i]) { int v=to[i]; if(v==fa) continue; deep[v]=deep[x]+1; dfs(v,x); } } inline void work(){ n=tot=getint(); int len,last; for(int i=2;i<=n;i++) { father[i]=getint(); scanf("%s",s+1); len=strlen(s+1); last=father[i]; for(int j=1;j<len;j++) { tot++; f[tot][0]=last; g[tot][0]=s[j]-'a'+1; link(last,tot); last=tot; } link(last,i); f[i][0]=last;/*!!!*/ g[i][0]=s[len]-'a'+1; } init(); scanf("%s",s+1); m=strlen(s+1); Ha=0; for(int i=m;i>=1;i--) Ha=Ha*base+s[i]-'a'+1,Ha%=mod; dfs(1,0); printf("%d",ans); } int main() { work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。