这题的题面好像比上一题好理解一点点??但原谅我样例可能理解了半年。。。(其实后来发现luogu讨论里有对于样例的提问和解释,但是很开心的是,我并没有看到。。/微笑/)
这里对于一样不理解样例的人说一句,这里的num数组并不是存储最长的子串长度,而是满足条件的子串个数,嗯对
那经过我这半个小时对于样例的热切探讨,还是15分钟打了个板子,在预处理中加了个类似于递推的语句求解num的简化版数组,再通过kmp主函数中让读入的数组自己跟自己kmp(。。没有别的含义哦不要乱想。。),处理出num真正的数组
1 #include<set> 2 #include<map> 3 #include<list> 4 #include<queue> 5 #include<stack> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9 #include<vector> 10 #include<bitset> 11 #include<memory> 12 #include<utility> 13 #include<cstdio> 14 #include<sstream> 15 #include<iostream> 16 #include<cstdlib> 17 #include<cstring> 18 #include<algorithm> 19 using namespace std; 20 const int mod=1000000007; 21 22 int n,lzy; 23 long long zz,z,y; 24 int next[1000005],num[1000005]; 25 char zy[1000005]; 26 27 inline long long ma(long long a,int b){return a>b?a:b;}//手写min max函数快一丢丢 28 29 void advance(){//预处理(这个单词我昨天晚上现场百度的emmmmm) 30 next[0]=-1;//赋初值 31 next[1]=0; 32 num[1]=1; 33 for(int i=1,j=0;i<lzy;i++){ 34 while(j&&zy[i]!=zy[j]){ 35 j=next[j]; 36 } 37 if(zy[i]==zy[j]){ 38 j++; 39 } 40 next[i+1]=j; 41 num[i+1]=num[j]+1;//处理出伪num数组 42 } 43 } 44 45 void KMP(){//kmp 46 for(int i=1,j=0;i<lzy;i++) { 47 while(j>=0&&zy[i]!=zy[j]){ 48 j=next[j]; 49 } 50 j++; 51 while((j*2)>(i+1)){//若子串过长,则缩短 52 j=next[j]; 53 } 54 y*=(long long)(num[j]+1);//强制转换longlong 55 y%=mod;//取模 56 } 57 } 58 59 int main(){ 60 scanf("%d",&n); 61 while(n--){ 62 cin>>zy; 63 lzy=strlen(zy); 64 z=0; 65 y=1; 66 advance(); 67 KMP(); 68 printf("%lld\n",y);//记得要用longlong 69 } 70 return 0; 71 }
lalala睡觉了,白白
哦对了原谅我就写了三题,那是因为我tm昨天晚上脑子都要炸了。。kmp本身就不好理解,还tm变着花玩???我丢告辞!!