Codeforces 235C Cyclical Quest
题目大意
给你一个原始串s,接下来n个询问,每次询问给出一个字符串,问原始串中有多少子串是给出字符串的循环同构串。
题解
对于原始串s建立sam,求出sam每个节点right集合的大小。对于每个询问,把询问串最小循环节-1复制一份拼在询问串的后面然后在sam上走。如果匹配长度超过length(询问串),这时候需要跳到parent的树上这个节点祖先中第一个节点的dis大于length的地方(因为直接加我wa了一发),再ans+=当前节点right集合的大小。
1 program j01; 2 const maxn=3000086;mxn=200086; 3 type node=record son:array['a'..'z']of longint;fa,dis:longint; end; 4 var s:ansistring; 5 t:array[0..maxn]of node; 6 ch:array[0..mxn]of char; 7 sum,tmp,r:array[0..maxn]of longint; 8 i,tt,n,len,last,root,ans,len2:longint; 9 next:array[0..mxn]of longint; 10 11 function newnode(d:longint):longint; 12 begin 13 inc(tt);t[tt].dis:=d;exit(tt); 14 end; 15 16 procedure ins(ch:char); 17 var p,np,q,nq:longint;i:char; 18 begin 19 p:=last;np:=newnode(t[p].dis+1);last:=np; 20 r[np]:=1; 21 while(t[p].son[ch]=0)and(p>0) do 22 begin 23 t[p].son[ch]:=np;p:=t[p].fa; 24 end; 25 if p=0 then t[np].fa:=root else 26 begin 27 q:=t[p].son[ch]; 28 if t[q].dis=t[p].dis+1 then t[np].fa:=q else 29 begin 30 nq:=newnode(t[p].dis+1); 31 for i:='a' to 'z' do t[nq].son[i]:=t[q].son[i]; 32 t[nq].fa:=t[q].fa; 33 t[q].fa:=nq;t[np].fa:=nq; 34 while t[p].son[ch]=q do 35 begin 36 t[p].son[ch]:=nq;p:=t[p].fa; 37 end; 38 end; 39 end; 40 end; 41 42 procedure build; 43 var i,p:longint; 44 begin 45 last:=1;root:=1;tt:=1;len:=length(s); 46 for i:=1 to len do ins(s[i]); 47 fillchar(sum,sizeof(sum),0); 48 for i:=1 to tt do inc(sum[t[i].dis]); 49 for i:=1 to len do inc(sum[i],sum[i-1]); 50 for i:=tt downto 1 do 51 begin 52 tmp[sum[t[i].dis]]:=i;dec(sum[t[i].dis]); 53 end; 54 for i:=tt downto 1 do 55 begin 56 p:=tmp[i];inc(r[t[p].fa],r[p]); 57 end; 58 end; 59 60 procedure getnext; 61 var i,j:longint; 62 begin 63 next[1]:=0;j:=0;len:=length(s); 64 for i:=2 to len do 65 begin 66 while(j>0)and(s[j+1]<>s[i])do j:=next[j]; 67 if s[j+1]=s[i] then inc(j); 68 next[i]:=j; 69 end; 70 end; 71 72 procedure getch; 73 var x,i:longint; 74 begin 75 for i:=1 to len do ch[i]:=s[i]; 76 x:=len-next[len]; 77 if (x=0)or(len mod x<>0) then x:=len; 78 dec(x); 79 for i:=len+1 to len+x do ch[i]:=s[i-len]; 80 len2:=len+x; 81 end; 82 83 procedure work; 84 var j:char;i,dis,p:longint; 85 begin 86 p:=root;dis:=0; 87 for i:=1 to len2 do 88 begin 89 j:=ch[i]; 90 if t[p].son[j]>0 then 91 begin 92 p:=t[p].son[j];inc(dis); 93 end else 94 begin 95 while(p>0)and(t[p].son[j]=0)do p:=t[p].fa; 96 if p=0 then 97 begin 98 p:=root;dis:=0; 99 end else 100 begin 101 dis:=t[p].dis+1;p:=t[p].son[j]; 102 end; 103 end; 104 while t[t[p].fa].dis>=len do 105 begin 106 p:=t[p].fa;dis:=t[p].dis; 107 end; 108 if dis>=len then inc(ans,r[p]); 109 end; 110 end; 111 112 begin 113 readln(s); 114 build; 115 readln(n); 116 for i:=1 to n do 117 begin 118 readln(s); 119 getnext;getch; 120 ans:=0;work; 121 writeln(ans); 122 end; 123 end.