题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5880
开结构体,不大好,因为很容易爆空间
额 下面的代码 用的时候就new出来,用完就delete,但还是MLE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cctype>
using namespace std;
const int maxn=1000000+5;
const int letters=26;
struct CNode{
CNode *pChilds[letters];
CNode *pPrev;
bool bBadNode,end; int len;
CNode(){
for(int i=0;i<letters;i++) pChilds[i]=NULL;
bBadNode=end=false; len=0;
pPrev=NULL;
}
};
char str[maxn];
CNode* Q[maxn];
int head,tail;
void BuildDfa(CNode* root0,CNode* root1)
{
for(int i=0;i<letters;i++)
root0->pChilds[i]=root1;
root1->pPrev=root0;
root0->pPrev=NULL;
head=tail=0;
Q[head++]=root1;
while(head!=tail)
{
CNode *root=Q[tail++];
for(int i=0;i<letters;i++)
{
CNode *p=root->pChilds[i];
if(p==NULL) continue;
CNode *pPrev=root->pPrev;
while(pPrev){
if(pPrev->pChilds[i]!=NULL){
p->pPrev=pPrev->pChilds[i];
if(p->pPrev->bBadNode)
p->bBadNode=true;
break;
}
else pPrev=pPrev->pPrev;
}
Q[head++]=p;
}
}
}
bool SearchDfa(CNode* root,char *s)
{
CNode *p=root;
for(int i=0;s[i];i++){
if(!isalpha(s[i])) continue;
for(;;){
if(p->pChilds[tolower(s[i])-'a']!=NULL){
p=p->pChilds[tolower(s[i])-'a'];
CNode* pPrev=p;
while(pPrev->bBadNode){
if(pPrev->end){
for(int j=0;j<p->len;j++)
s[i-j]='*';
break;
}
pPrev=pPrev->pPrev;
}
break;
}
else p=p->pPrev; //到前驱节点
}
}
return false;
}
void Insert(CNode *root,char *s)
{
for(int i=0;s[i];i++)
{
if(root->pChilds[s[i]-'a']==NULL)
root->pChilds[s[i]-'a']=new CNode;
root=root->pChilds[s[i]-'a'];
}
root->bBadNode=true;
root->end=true;
root->len=strlen(s);
}
void Dele(CNode* root){
for(int i=0;i<letters;i++)
if(root->pChilds[i]!=NULL)
Dele(root->pChilds[i]);
delete root;
}
int main()
{
int T,n; cin>>T;
while(T--)
{
CNode *root0=new CNode,*root1=new CNode;
cin>>n;
while(n--){
scanf("%s",str);
Insert(root1,str);
}
BuildDfa(root0,root1);
getchar();
gets(str);
SearchDfa(root1,str);
cout<<str<<endl;
Dele(root1);
delete root0;
}
return 0;
}
试了一下,如果数组没用到,不会计入memory,但是结构体一旦new出来,就要全部算空间
并且什么都不干,单单开个1000000的数组,只要memset就会MLE
以下这句话摘自:博客
Q神说不要用memset一次性清空数组,超内存是我一次性memset数组导致的,将没有用的空间也用上了,于是试了下不一次性memset数组,果断不超了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cctype>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1000000+5;
const int letters=26;
const int pPrev=26;
const int len=27;
const int bBadNode=28;
const int End=29;
int nNode;
int tree[maxn][30];
char str[maxn];
int NewNode() //用一个就开一个空间
{
for(int i=0;i<30;i++) tree[nNode][i]=-1;
nNode++;
return nNode-1;
}
void init()
{
nNode=2;
for(int i=0;i<30;i++) tree[0][i]=tree[1][i]=-1;
}
void Insert(int root,char *s)
{
for(int i=0;s[i];i++){
if(tree[root][s[i]-'a']==-1)
tree[root][s[i]-'a']=NewNode();
root=tree[root][s[i]-'a'];
}
tree[root][len]=strlen(s);
tree[root][bBadNode]=1;
tree[root][End]=1;
}
void BuildDfa()
{
for(int i=0;i<letters;i++)
tree[0][i]=1;
tree[1][pPrev]=0;
tree[0][pPrev]=-1;
queue<int> Q;
Q.push(1);
while(!Q.empty())
{
int root=Q.front(); Q.pop();
for(int i=0;i<letters;i++)
{
int p=tree[root][i];
if(p==-1) continue;
int pp=tree[root][pPrev];
while(pp!=-1)
if(tree[pp][i]!=-1){
tree[p][pPrev]=tree[pp][i];
if(tree[tree[p][pPrev]][bBadNode]==1)
tree[p][bBadNode]=1;
break;
}
else pp=tree[pp][pPrev];
Q.push(p);
}
}
}
void SearchDfa(char *s)
{
int p=1;
for(int i=0;s[i];i++)
{
if(!isalpha(s[i])) {
p=1; continue;
}
for(;;){
if(tree[p][tolower(s[i])-'a']!=-1){
p=tree[p][tolower(s[i])-'a'];
int pp=p;
while(tree[pp][bBadNode]==1){
if(tree[pp][End]==1){
for(int j=0;j<tree[pp][len];j++)
s[i-j]='*';
break;
}
else pp=tree[pp][pPrev];
}
break;
}
else p=tree[p][pPrev];
}
}
}
int main()
{
int T,n; scanf("%d",&T);
while(T--)
{
scanf("%d",&n); nNode=2;
init();
while(n--){
scanf("%s",str);
Insert(1,str);
}
BuildDfa();
getchar();
gets(str);
SearchDfa(str);
cout<<str<<endl;
}
return 0;
}