本题是KMP的next数组的灵活运用。
具体就是看最后整个数列的最后一个字母,能有多少前缀。
理解了next数组就很容易了。
#include <stdio.h> #include <string.h> #include <vector> using std::vector; const int MAX_N = 400001; char name[MAX_N]; int next[MAX_N], len; void genNext() { for (int i = 1, j = 0; i < len; ) { if (name[i] == name[j]) next[i++] = ++j; else if (j > 0) j = next[j-1]; else i++; } } void getPreSuf(vector<int> &rs) { rs.clear(); int i = len; while (i > 0) { rs.push_back(i); i = next[i-1]; } } int main() { vector<int> rs; while (gets(name)) { len = strlen(name); memset(next, 0, sizeof(int)*len); genNext(); getPreSuf(rs); for (int i = (int)rs.size()-1; i >= 0; i--) { printf("%d ", rs[i]); } putchar('\n'); } return 0; }
要使嫌保存结果麻烦,也可以直接递归打印出来,不需要保存中间结果了:
#include <stdio.h> #include <string.h> const int MAX_N = 400001; char name[MAX_N]; int next[MAX_N], len; void genNext() { for (int i = 1, j = 0; i < len; ) { if (name[i] == name[j]) next[i++] = ++j; else if (j > 0) j = next[j-1]; else i++; } } void printPreSuf(int i) { if (i > 0) { printPreSuf(next[i-1]); printf("%d ", i); } } int main() { while (gets(name)) { len = strlen(name); memset(next, 0, sizeof(int)*len); genNext(); printPreSuf(len); putchar('\n'); } return 0; }
POJ 2752 Seek the Name, Seek the Fame KMP题解
时间: 2024-11-14 21:12:56