Period(poj 1961)
原题链接
题目类型:KMP最小重复子串
#include<iostream>
#include<string>
using namespace std;
#define NMAX 1000100
char s[NMAX];
int Lat[NMAX];
int N;
void get_Lat(int* Lat, char* s2, int lens) {
//用于构建s2的Lat数组,kmp的前奏
int t1 = 0, t2;
Lat[0] = t2 = -1;
while (t1 < lens) { //逐步向前寻找t2
if (t2 == -1 || s2[t1] == s2[t2]) {
Lat[t1 + 1] = t2 + 1;
t1++;
t2++; //t2首先指向的是Lat[t1-1]即前一个的位置
}
else t2 = Lat[t2]; //保证了0 与t1-1等对的一致,若出现了不等,则会直接
}
}
int main() {
int num = 1;
while(1) {
cin >> N;
if (!N) break;
cin >> s;
get_Lat(Lat, s, N);
// for (int i = 1; i < strlen(s); i++) cout << Lat[i] << " ";
cout << "Test case #"<<num++<<endl;
for (int i = 2; i <= N; i++) {
//cout << "length"<<strlen(s) << endl;
int start = i;
int standard = start - Lat[start];
if (i % standard == 0 && i / standard>1) cout << i << " " << i / standard << endl;
}
cout << endl;
}
}
tip:
1.如果在循环中使用i<=strlen(s)的话会出现超时错误(tle警告)
2.在对该题的求解过程中,应该去推导得到关于最小重复子串个数的公式,若依据nxt数组逐步向前遍历的话,会超时。
Oulipo(poj 2406)
原题链接
题目类型:KMP字符串匹配
#include<iostream>
#include<string>
using namespace std;
#define WMAX 10010
#define TMAX 1000010
char W[WMAX];
char T[TMAX];
int nxt[TMAX];
int tl, wl;
int N;
int num;
void get_Lat(int* nxt, char* s, int lens) {
nxt[0] = -1;
int t1 = 0, t2 = -1;
while (t1 < lens) {
if (t2 == -1 || s[t1] == s[t2]) {
nxt[t1 + 1] = t2 + 1;
t1++;
t2++;
}
else t2 = nxt[t2];
}
}
int main() {
cin >> num;
while (num--) {
//scanf_s("\n%s\n%s", W, T);
int times = 0;
cin >> W >> T;
tl = strlen(T), wl = strlen(W);
get_Lat(nxt, W, wl);
int t1 = 0, t2 = 0;
while (t1 < tl && t2 < wl) {
if (t2==-1 || T[t1] == W[t2]) {
t1++, t2++;
}
else t2 = nxt[t2]; //注意这里仅和W串有关系
if (t2 == wl) {
times++;
t2 = nxt[t2];//注意在能够进行一个完全的匹配后应该对t2进行更新
}
}
cout << times << endl;
}
}