这题看了一个解题报告说可以不用自动机做,单用trie树就可以过,于是就做做呗。
思路是这样的:因为每个模式串长度不超过6,所以可以建一棵6层的trie树,从主串的第一个开始枚举长度为6的字串建树,树节点有三个数据域,一个是next数组指向下一个字母,一个是over代表到达当前字母所形成的串可以覆盖的出现次数,notover代表不可以覆盖的次数,last_pos代表当前字母上一次的位置,用于不覆盖情况用的。接着就乱搞,NND,指针竟然爆内存!!!只好改用数组
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen ("input.txt","r",stdin)
#define FF freopen ("output.txt","w",stdout)
#define N 100005
char str[N];
struct node {
int next[26];
int over;
int notover;
int last_pos;
}p[400000];
int kk;
void init(int pos) {
int i;
for (i = 0 ;i < 26; i++)p[pos].next[i] = -1;
p[pos].last_pos = -1;
p[pos].notover = 0;
p[pos].over = 0;
}
void Build(char *s,int st) {
int pos = 0;
int i;
for (i = 0; s[i]; i++) {
int id = s[i] - 'a';
if (p[pos].next[id] == -1) {
init(kk);
p[pos].next[id] = kk++;
} pos = p[pos].next[id];
if (p[pos].last_pos < st) {
p[pos].notover++;
p[pos].last_pos = st+i;
}
p[pos].over++;
}
}
int gao(int op,char *s) {
int pos = 0;
int i;
int sum = 0;
for (i = 0; s[i]; i++) {
int id = s[i] - 'a';
if (p[pos].next[id] != -1) {
pos = p[pos].next[id];
} else return 0;
}
if (!op) {
sum += p[pos].over;
} else {
sum += p[pos].notover;
}
return sum;
}
int main () {
char ss[7];
int ca = 1;
while (scanf("%s",str) !=EOF) {
int n;
int i,j;
int len = strlen(str);
init(0);
int cnt;
kk = 1;
for (i = 0; str[i]; i++) {
cnt = 0;
for (j = i; j < i + 6 && j < len; j++) {
ss[cnt++] = str[j];
}
ss[cnt] = '\0';
Build(ss,i);
}
scanf("%d",&n);
printf("Case %d\n",ca++);
while (n--) {
int op;
scanf("%d%s",&op,ss);
printf("%d\n",gao(op,ss));
}
puts("");
}
return 0;
}
贴一个指针爆内存版
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen ("input.txt","r",stdin)
#define FF freopen ("output.txt","w",stdout)
#define N 100005
char str[N];
struct node {
node *next[26];
int over;
int notover;
int last_pos;
node () {
memset(next,NULL,sizeof(next));
over = 0;
notover = 0;
last_pos = -1;
};
};
void Build(char *s,node *root,int st) {
node *p;
p = root;
int i;
for (i = 0; s[i]; i++) {
int id = s[i] - 'a';
if (p->next[id] == NULL) {
p->next[id] = new node ;
}
if (p->next[id]->last_pos < st) {
p->next[id]->notover++;
p->next[id]->last_pos = st+i;
}
p->next[id]->over++;
p = p->next[id];
}
}
int gao(int op,char *s,node *root) {
node *p;
p = root;
int i;
int sum = 0;
for (i = 0; s[i]; i++) {
int id = s[i] - 'a';
if (p->next[id]) {
p = p->next[id];
} else return 0;
}
if (!op) {
sum += p->over;
} else {
sum += p->notover;
}
return sum;
}
int main () {
char ss[7];
int ca = 1;
while (scanf("%s",str) !=EOF) {
int n;
int i,j;
int len = strlen(str);
node *root = new node();
int cnt;
for (i = 0; str[i]; i++) {
cnt = 0;
for (j = i; j < i + 6 && j < len; j++) {
ss[cnt++] = str[j];
}
ss[cnt] = '\0';
Build(ss,root,i);
}
scanf("%d",&n);
printf("Case %d\n",ca++);
while (n--) {
int op;
scanf("%d%s",&op,ss);
printf("%d\n",gao(op,ss,root));
}
puts("");
}
return 0;
}
本文介绍了一种利用Trie树解决字符串匹配问题的方法,通过构建Trie树并进行深度枚举,实现了对主串中长度为6的子串进行匹配分析,解决了实际编程中的复杂性问题。
1735

被折叠的 条评论
为什么被折叠?



