【KMP】BZOJ3670-[Noi2014]動物園

【題目大意】
[依然借用別人的歸納]給定一個長爲L的字符串(L<=100W),求一個num數組,num[i]表示長度爲i的前綴中字符串S’的數量,其中S‘既是該前綴的前綴也是該前綴的後綴,且|S'|*2<=i
【思路】
KMP中next數組的變形。先算一次next數組和dep數組,其中dep數組表示當前前綴通過j=next[j]能夠到達-1,這個值其實就是num數組的雛形。而後再進行一次求解next數組,每次前綴不斷進行j=next[j],直到知足|S'|*2<=i。此時的dep[j]就是當前前綴的num值,因爲前一次求解next數組預處理,這個值能夠在O(1)時間內求解。ios

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define LL long long
 6 #define mod 1000000007
 7 const int MAXN=1000000+500;
 8 using namespace std;
 9 int n;
10 char p[MAXN];
11 int next[MAXN],dep[MAXN],next2[MAXN];
12 int len;
13 
14 void getnext()
15 {
16     int i=0,j=-1;
17     next[i]=j;
18     dep[i]=0;
19     while (i<len)
20     {
21         if (j==-1 || p[i]==p[j])
22         {
23             dep[++i]=dep[++j]+1;
24             next[i]=j;
25         }
26         else j=next[j];
27     }
28 }
29 
30 void getans()
31 {
32     LL ans=1;
33     int i=0,j=-1;
34     while (i<len)
35     {
36         if (j==-1 || p[i]==p[j])
37         {
38             i++,j++;
39             while (j!=-1 && (j<<1)>i) 
40                 j=next[j];
41             if (j!=-1 && i!=-1) ans=ans*(LL)(dep[j]+1) % mod;
42         }
43         else j=next[j];
44     }
45     printf("%lld\n",ans);
46     
47 
48 }
49 
50 int main()
51 {
52     scanf("%d",&n);
53     for (int i=0;i<n;i++)
54     {
55         scanf("%s",p);
56         len=strlen(p);
57         getnext();
58         getans();
59     }
60     return 0;
61 }
相關文章
相關標籤/搜索