您的位置:首页 > 其它

【HDU 3518】Boring counting【扩展KMP】

2014-07-23 08:34 351 查看
题意:给出一个串,找出一个最长字串,不重叠的出现次数大于1次,输出这个字串的长度。

思路:我们对母串的每一个后缀都和母串做一遍扩展KMP,这样就可以知道母串和每一个后缀都求出一个最长公共字串的长度,记录ex[i][j]为母串第j个位置开始与第i个后缀所形成的最长公共前缀的长度,则记录maxid[j]表示从母串的j位开始,最长出现次数大于1次且不重叠的字串长度。可以知道maxid[j] = max(maxid[j], min(i-j, ex[i]][j]));

每一个maxid[j]都可以产生maxid[j]个答案,接下来就是对于答案判重的情况。我们可以用字典树判重,每一个maxid[j]所代表的字串一次跑一下字典树,最后字典树的节点个数就是所求的答案。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1010

char s
, hz
;

void exkmp(char *s1, char *s2, int *next, int *ex) {
int i, j, p;
for (i = 0,j = 0,p = -1;s1[i] != '\0';i++,j++,p--) {
if (p == -1) {
j = 0;
do p++; while (s1[i+p] != '\0' && s1[i+p] == s2[j+p]);
ex[i] = p;
}
else if (next[j] < p) ex[i] = next[j];
else if (next[j] > p) ex[i] = p;
else {
j = 0;
while (s1[i+p] != '\0' && s1[i+p] == s2[j+p]) p++;
ex[i] = p;
}
}
ex[i] = 0;
}

int next
,extand
, mxid
;

struct Tr{
Tr *c[26];
Tr() {
for (int i = 0;i < 26;i++) c[i] = NULL;
}
}*root;

int cnt;

void ins(int st, int len) {
int i, j;
Tr *p = root;
for (i = 0;i < len;i++) {
j = s[i+st]-'a';
if (p->c[j] == NULL) {
p->c[j] = new Tr();
cnt++;
}
p = p->c[j];
}
}

int main() {
int len, i, j;
while (~scanf("%s", s), s[0] != '#') {
len = strlen(s);
memset(mxid, 0, sizeof(mxid));
for (i = 1;i < len;i++) {
exkmp(s+i+1, s+i, next, next+1);
exkmp(s, s+i, next, extand);
for (j = 0;j < i;j++) {
mxid[j] = max(mxid[j], min(i-j, extand[j]));
}
}
root = new Tr();
cnt = 0;
for (i = 0;i < len;i++) {
ins(i, mxid[i]);
}
printf("%d\n", cnt);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: