【Wannafly挑战赛9-B】数一数
链接:https://www.nowcoder.net/acm/contest/71/B
题目就不贴了。。
设res[i]为第i行的最终结果,可以想到,res[i]为0或不为0。长度不是最短的字符串res一定0,因为res是所有子串数量的乘积,对于每个字符串,只有长度最短的字符串乘过之后才会有结果,其余的res都是0。有多个长度最短的,结果都一样,总之...看代码就懂了(逃。之后就是KMp了(好长时间没复习kmp都忘了惹Σ(゚д゚;)
上代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int mod = 998244353; 5 const int N = 1e6+3; 6 string s[N]; 7 char s1[N*2]; 8 int id[N], Next[N*2]; 9 LL res[N]; 10 void make(string s, int m) 11 { 12 int i, j; 13 for(i=1, j=0; i<m; i++) 14 { 15 while(j > 0 && s[i] != s[j]) 16 j = Next[j-1]; 17 if(s[i] == s[j]) 18 j++; 19 Next[i] = j; 20 } 21 } 22 int kmp(string s1, string s2) 23 { 24 int i, j, num = 0; 25 int l1 = s1.size(); 26 int l2 = s2.size(); 27 Next[0] = 0; 28 make(s1, l1); 29 for(i = 0, j = 0; i < l2; i++) 30 { 31 while(j > 0 && s1[j] != s2[i]) 32 j = Next[j-1]; 33 if(s1[j] == s2[i]) 34 j++; 35 if(j == l1) 36 { 37 num++; 38 j = Next[j-1]; 39 } 40 } 41 return num; 42 } 43 int main() 44 { 45 int n, i, j; 46 cin>>n; 47 for(i = 1; i <= n; i++) 48 { 49 scanf("%s", s1); 50 s[i] = s1; 51 id[i] = i;//用id标号来给长度从小到大排序 52 } 53 sort(id+1, id+1+n, [](int x, int y){return s[x]. size()<s[y].size();});//又学会一种偷懒+的写法(°∀°)ノ 54 int m = s[id[1]].size(); 55 res[id[1]] = 1; 56 for(j = 2; j <= n; j++) 57 res[id[1]] = (res[id[1]]*kmp(s[id[1]], s[j])%mod)%mod; 58 for(i = 2; i <= n; i++) 59 { 60 if(s[id[i]].size() != m) break; 61 if(s[id[i]].size() == m) res[id[i]] = res[id[1]]; 62 } 63 for(i = 1; i <= n; i++) 64 printf("%lld\n", res[i]); 65 return 0; 66 }