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.
View Code

 

posted @ 2017-04-22 16:20  OldJang  阅读(176)  评论(0编辑  收藏  举报