题目传送门
解题思路:
f[i]表示到第i位可获得的最大分割次数,对于每个f[i]都可由其符合条件的前缀转移过来,条件就是当前串除了前缀的剩余字符里有所给单词,然后一看,这不是在剩余字符里找有没有所给单词吗?所以果断KMP,其实本题好像不用KMP,暴力模拟就可以,但是为了练习KMP装逼,所以就写一下.
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 4 using namespace std; 5 6 string l,p,a[501]; 7 int n,kmp[501][301],f[501]; 8 9 inline int max(int s,int d) { 10 if(s > d) return s; 11 return d; 12 } 13 14 int main() { 15 cin >> p; 16 l = " " + p; 17 scanf("%d",&n); 18 for(int i = 1;i <= n; i++) { 19 cin >> p; 20 a[i] = " " + p; 21 int len = a[i].length() - 1,k = 0; 22 for(int j = 2;j <= len; j++) { 23 while(k != 0 && a[i][j] != a[i][k+1]) k = kmp[i][k]; 24 if(a[i][j] == a[i][k+1]) k++; 25 kmp[i][j] = k; 26 } 27 } 28 for(int i = 1;i <= l.length() - 1; i++) { 29 for(int j = 1;j <= i; j++) { 30 string u = " " + l.substr(j,i-j+1); 31 int o; 32 bool vis = 0; 33 for(int k = 1;k <= n; k++) { 34 o = 0; 35 for(int p = 1;p <= u.length() - 1; p++) { 36 while(o != 0 && u[p] != a[k][o+1]) o = kmp[k][o]; 37 if(u[p] == a[k][o+1]) o++; 38 if(o == a[k].length() - 1) { 39 vis = 1; 40 break; 41 } 42 } 43 if(vis) break; 44 } 45 if(vis) 46 f[i] = max(f[i],f[j-1] + 1); 47 } 48 } 49 printf("%d",f[l.length()-1]); 50 return 0; 51 }