TLE,TLE,各种姿势还是TLE,改递归为非递归,还是TLE。
求解。
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
typedef int Nodelink;
const int maxn = 1000101;//内存池大小
Nodelink Node[maxn][3]; //三叉树的节点,预开内存的速度是动态开不可比拟的(TLE了一晚的教训)。
Nodelink fail[maxn];
int cnt[maxn]; //以该节点为结束的字符串的数目。
char elem[maxn]; //节点保存的字符。
int top; //模拟内存池地址
int link[maxn];
Nodelink newNode(char ch) //创建一个节点
{
top ++;
Node[top][0] = Node[top][1] = Node[top][2] = 0;
cnt[top] = 0;
elem[top] = ch;
return top;
}
char sub[5][6] = {"","nihao","hao","hs","hsr"};
void insert(char str[], int idx) //插入模式串
{
int len = strlen(str);
Nodelink p = 1;
for(int i = 0; i < len; i++) {
if(!Node[p][2])
Node[p][2] = newNode(str[i]);
p = Node[p][2];
while(elem[p] != str[i]) { //二叉树插入元素,保证有序
if(str[i] < elem[p]) {
if(!Node[p][0]) Node[p][0] = newNode(str[i]);
p = Node[p][0];
}
else {
if(!Node[p][1]) Node[p][1] = newNode(str[i]);
p = Node[p][1];
}
}
}
cnt[p] = idx; //以编号为p的结点为结尾的模式串的输入序号。
}
char str[30];
void print(Nodelink p, int len) //输出模式串
{
if(Node[p][0])
print(Node[p][0], len);
str[len] = elem[p];
if(cnt[p]) {
str[len + 1] = '\0';
for(int i = 0; i < cnt[p]; i++)
printf("%s\n", str);
}
if(Node[p][2])
print(Node[p][2], len + 1);
if(Node[p][1])
print(Node[p][1], len);
}
queue <int> q;
int findFail(Nodelink fp, Nodelink p) //查找合适p结点的fail点
{
if(Node[fp][0] && findFail(Node[fp][0], p))
return 1;
if(elem[fp] == elem[p])
{
fail[p] = fp;
return 1;
}
if(Node[fp][1] && findFail(Node[fp][1], p))
return 1;
return 0;
}
void travelPre(Nodelink p, Nodelink pre)
{
if(Node[p][0])
travelPre(Node[p][0], pre);
Nodelink tmp = fail[pre];
while(tmp && !findFail(Node[tmp][2], p))
tmp = fail[tmp];
if(tmp == 0)
fail[p] = 1;
q.push(p);
if(Node[p][1])
travelPre(Node[p][1], pre);
}
void getFail() //生成fail指针
{
while(!q.empty()) q.pop();
q.push(1);
fail[1] = 0;
while(!q.empty())
{
Nodelink pre = q.front();
q.pop();
if(Node[pre][2])
travelPre(Node[pre][2], pre);
}
}
int matchCH(char ch, Nodelink p, Nodelink &pre, int idx)
{
if(Node[p][0] && matchCH(ch, Node[p][0], pre, idx))return 1;
if(elem[p] == ch)
{
pre = p;
int fp = p;
while(fp) //查找是否含有以元素elem[p]结尾的模式串。
{
if(cnt[fp])
printf("%s matches string end at %d.\n", sub[cnt[p]] ,idx);
fp = fail[fp];
}
return 1;
}
if(Node[p][1] && matchCH(ch, Node[p][1], pre, idx))return 1;
return 0;
}
void match(char pattern[])
{
int idx = 0;
Nodelink p = 1;
while(idx < strlen(pattern))
{
while(p && !matchCH(pattern[idx] , Node[p][2], p, idx))
{
p = fail[p];
}
if(p == 0) p = 1;
idx ++;
}
}
int main()
{
top = 0;
newNode('\0');
char pattern[] = "sdmfhsgnshejfgnihaofhsrnihao";
for(int i = 1; i < 5; i++)
insert(sub[i], i);
getFail();
//print(Node[1][2], 0);
match(pattern);
return 0;
}
hdoj-2222题没过的代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
typedef int Nodelink;
const int maxn = 1000101;//内存池大小
Nodelink Node[maxn][3]; //三叉树的节点,预开内存的速度是动态开不可比拟的(TLE了一晚的教训)。
Nodelink fail[maxn];
int cnt[maxn]; //以该节点为结束的字符串的数目。
char elem[maxn]; //节点保存的字符。
int top; //模拟内存池地址
char str[60];
char pattern[1000010];
Nodelink newNode(char ch) //创建一个节点
{
top ++;
Node[top][0] = Node[top][1] = Node[top][2] = 0;
cnt[top] = 0;
elem[top] = ch;
return top;
}
void insert(char str[]) //插入模式串
{
int len = strlen(str);
Nodelink p = 1;
for(int i = 0; i < len; i++) {
if(!Node[p][2])
Node[p][2] = newNode(str[i]);
p = Node[p][2];
while(elem[p] != str[i]) { //二叉树插入元素,保证有序
if(str[i] < elem[p]) {
if(!Node[p][0]) Node[p][0] = newNode(str[i]);
p = Node[p][0];
}
else {
if(!Node[p][1]) Node[p][1] = newNode(str[i]);
p = Node[p][1];
}
}
}
cnt[p] ++; //以编号为p的结点为结尾的模式串的输入序号。
}
queue <int> q;
int findFail(Nodelink fp, Nodelink p) //查找合适p结点的fail点
{
if(Node[fp][0] && findFail(Node[fp][0], p))
return 1;
if(elem[fp] == elem[p])
{
fail[p] = fp;
return 1;
}
if(Node[fp][1] && findFail(Node[fp][1], p))
return 1;
return 0;
}
void travelPre(Nodelink p, Nodelink pre)
{
if(Node[p][0])
travelPre(Node[p][0], pre);
Nodelink tmp = fail[pre];
while(tmp && !findFail(Node[tmp][2], p))
tmp = fail[tmp];
if(tmp == 0)
fail[p] = 1;
q.push(p);
if(Node[p][1])
travelPre(Node[p][1], pre);
}
void getFail() //生成fail指针
{
while(!q.empty()) q.pop();
q.push(1);
fail[1] = 0;
while(!q.empty())
{
Nodelink pre = q.front();
q.pop();
if(Node[pre][2])
travelPre(Node[pre][2], pre);
}
}
int ans = 0;
int matchCH(char ch, Nodelink p, Nodelink &pre)
{
if(Node[p][0] && matchCH(ch, Node[p][0], pre))return 1;
if(elem[p] == ch)
{
pre = p;
int fp = p;
while(fp > 1) //查找是否含有以元素elem[p]结尾的模式串。这一段导致TLE
{
ans += cnt[fp];
fp = fail[fp];
}
return 1;
}
if(Node[p][1] && matchCH(ch, Node[p][1], pre))return 1;
return 0;
}
void match(char pattern[])
{
int idx = 0;
Nodelink p = 1;
int len = strlen(pattern);
while(idx < len)
{
while(p && !matchCH(pattern[idx] , Node[p][2], p))
{
p = fail[p];
}
if(p == 0) p = 1;
idx ++;
}
}
int main()
{
int t, n;
scanf("%d", &t);
while(t--)
{
top = 0;
ans = 0;
newNode('\0');
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%s",str);
insert(str);
}
scanf("%s", pattern);
getFail();
match(pattern);
printf("%d\n", ans);
}
return 0;
}